2017-10-17 159 views
-3

因此,我剛剛開始使用Ubuntu。 我正在構建這個非常簡單的程序,它可以讓我存儲一些數據並在稍後讀回。無法讀取Ubuntu中的.dat或.bin文件「Segmentation fault(核心轉儲)」

使用C++,fstream,一些對象存儲在.dat文件中。

// function to store 
void storeRecord(Record r){ 
    fstream afile; 
    afile.open("file.dat" , ios::out | ios::binary | ios::app); 
    afile.write(reinterpret_cast <const char*> (&r), sizeof(r)); 
    afile.close(); 
} 

但當我嘗試(調用查詢()函數)從同一個文件中讀取,我得到「分割故障(核心轉儲)」

void query(){ 
     Record r; 
     fstream afile; 
     afile.open("file.dat", ios::in | ios::binary); 
     while(afile.read(reinterpret_cast <char*> (&r), sizeof(r))){ 
      // do something 
     } 
     afile.close(); 
} 

這用來工作在窗戶上。這是爲什麼?

#include <iostream> 
#include <string> 
#include <fstream> 

using namespace std; 

class Record{ 
public: 
    // Constructors 
    Record(); 
    Record(string accountID, string name, string deptID, string password,   int role); 
    ~Record(); 

    // Assessors and Mutators 
    string getAccountID(); 
    string getName(); 
    string getDeptID(); 
    string getPW(); 
    int getRole(); 

    void setAccountID(string accountID); 
    void setName(string name); 
    void setDeptID(string deptID); 
    void setPW(string PW); 
    void setRole(int role); 

    // Other functions 
    string toString(); 

private: 
    string accountID; 
    string name; 
    string deptID; 
    string password; 
    int role;  // normal user, HR personal, admin 
}; 
+5

在查詢中沒有定義r。什麼是記錄?如果它不是POD,那麼你有bug。 – 2017-10-17 17:39:44

+0

有。在實際的程序中。我的錯誤在這裏。 oops – poh

+1

「Record」的類型是什麼?它是否有一些[vtable](https://en.wikipedia.org/wiki/Virtual_method_table)或一些(甚至是不正確的或內部的)指針? **你的代碼有[未定義的行爲](https://en.wikipedia.org/wiki/Undefined_behavior)**,所以你很幸運,它在Linux上崩潰(並且*不幸*它出現在Windows上) .... –

回答

1

您的Record包含std::string字段。

A string當然包含指針,並可能包含一些帶有虛函數的內部數據(因此有一個vtable,這是一個隱藏的指針);那麼這些數據就有了指針。並且string而不是 a POD(但是固定陣列的char將是例如像char name[48]; ....的字段)。

所以,你的代碼有undefined behavior所以你是幸運的,它crashes在Linux(和倒黴說,「出現」,它在Windows上工作)......順便說一句,當它是顯然「運行」(例如上您的Windows)文件格式保持「未定義」,您將無法再讀取由舊版本程序編寫的數據文件(或甚至是由較舊或不同的編譯器和C++標準庫編譯的相同源文件)。

Linux有ASLR;這可能可以解釋爲什麼你有一個segmentation fault。順便說一句,我猜測,如果您在相同的process(這對您不是特別有用)中編寫和讀取相同的數據文件,Linux可能不會崩潰。

要了解更多信息,您需要深入瞭解實施細節,而您不想。

顯然,您需要實施一些serialization機械。然後指定首先(詳細)你的file format(逐字節,endianness和「字大小」的問題和你的文件格式應該是「獨立」的),也許使用一些EBNF表示法。然後執行序列化例程,從基本POD類型開始。或者使用一些序列化庫。你的文件格式和代碼應該是可移植的(例如,樹莓派和Linux/PC上的相同程序應該能夠交換數據文件)。

順便說一句,我更喜歡使用一些文本格式,可能使用JSON,YAML(或XML)。或者考慮像SQLiteGDBM這樣的庫。在你的情況下,你的Record很容易映射到SQLite表中的行或JSON對象。也許你應該問你的老師是否允許使用它們......