2011-07-13 103 views
2

一段時間以來,我一直在嘗試使用C++將內存寫入文件緩衝區時遇到了一個非常奇怪的問題。這個問題只發生在MinGW上。當我在gcc/linux下編譯時,一切都很好。如何將內存寫入文件緩衝區進行變異?

Debugging Session displaying the problem

所以基本上,我正在寫從內存緩衝區代碼爲filebuffer,並在文件中的二進制表示最終被從我寫的內存不同。不,該文件稍後沒有被修改,我通過在關閉文件後使用調試器退出程序來保證這一點。我不知道這樣的事情甚至是可能的,我甚至用valgrind來查看是否有任何內存分配問題,但不是。

我會粘貼一些相關的代碼。

/// a struct holding information about a data file 
class ResourceFile { 
public: 
    string name; 
    uint32 size; 
    char* data; 

    ResourceFile(string name, uint32 size); 
}; 

ResourceFile::ResourceFile(string name, uint32 size) 
    : name(name), size(size) 
{ 
    // will be free'd in ResourceBuilder's destruction 
    data = (char*) malloc(size * sizeof(char)); 
} 


/// Build a data resource from a set of files 
class ResourceBuilder { 
public: 
    ofstream out; ///< File to put the resource into 
    vector<ResourceFile> input; ///< List of input strings 

    /// Add a file from disk to the resource 
    void add_file(string filename); 

    /// Create a file that the resource will be written to 
    void create_file(string filename); 

    ~ResourceBuilder(); 
}; 

void ResourceBuilder::create_file(string filename) { 
    // open the specified file for output 
    out.open(filename.c_str()); 
    uint16 number_files = htons(input.size()); 
    out.write((char*) &number_files, sizeof(uint16)); 

    foreach(vector<ResourceFile>,input,i) { 
     ResourceFile& df = *i; 
     uint16 name_size = i->name.size(); 
     uint16 name_size_network = htons(name_size); 
     out.write((char*) &name_size_network, sizeof(uint16)); 
     out.write(i->name.c_str(),name_size); 
     uint32 size_network = htonl(i->size); 
     out.write((char*) &size_network, sizeof(i->size)); 
     out.write(i->data, i->size); 
    } 

    out.close(); 

    /// \todo write the CRC 
} 

以下是如何分配內存的第一個地方。這是一個可能的錯誤來源,因爲我從別處拷貝了它而沒有詳細地理解它,但我真的不知道如何分配內存的方法可能是文件緩衝區輸出不同於內存的原因我正在寫作。

void ResourceBuilder::add_file(string filename) { 
    // loads a file and copies its content into memory 
    // this is done by the ResourceFile class and there is a 
    // small problem with this, namely that the memory is 
    // allocated in the ResourceFile directly, 
    ifstream file; 
    file.open(filename.c_str()); 

    filebuf* pbuf=file.rdbuf(); 

    int size=pbuf->pubseekoff (0,ios::end,ios::in); 
    pbuf->pubseekpos (0,ios::in); 

    ResourceFile df(filename,size); 

    pbuf->sgetn (df.data,size); 

    file.close(); 

    input.push_back(df); 
} 

我真的沒有想法。這也不是與我的編譯器設置有關的錯誤,因爲編譯MinGW下的代碼的其他人也會得到相同的錯誤。我現在唯一能想到的解釋是MinGW的filebuffer庫本身存在一個bug,但我真的不知道。

+0

量子力學! –

回答

5

您需要以二進制模式打開文件。當您在Windows上以文本模式打開它時,換行符(0x0A)將轉換爲CR/LF對(0x0D,0x0A)。在Linux上,您不會看到這一點,因爲Linux在文本文件中使用單個LF(0x0A)作爲行終止符,因此不會進行轉換。

傳遞ios::binary標誌的ostream::open方法:

out.open(filename.c_str(), ios::out | ios::binary); 

讀取二進制文件時,所以不執行相反的轉換,也應當使用這個標誌:

ifstream file; 
file.open(filename.c_str(), ios::in | ios::binary); 
+0

* facepalms *哦該死的,現在我覺得很蠢。看那段代碼的時間,並忽略這樣一個簡單的事情..無論如何,謝謝!這固定好了。太糟糕了,我不能接受兩個答案,因爲你們兩個在同一時間回答。 – cib

+0

@cib它發生在每個人身上,我發誓:P –

2

問題是你在文本模式下打開你的文件!在這種情況下,0x0a(換行)轉換爲0x0d0a(回車換行)。這就是您看到文件和內存有所不同的原因。

使用out.open(filename.c_str(), ios::binary | ios::out);

相關問題