2017-10-17 37 views
-3

最近、Ubuntuを最近使い始めました。 私はいくつかのデータを保存し、後でそこから読み戻すことができる非常にシンプルなプログラムを構築しています。Ubuntuの.datファイルや.binファイルを読み取れません "セグメンテーションフォールト(コアダンプ)"

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でない場合は、あなたのバグがあります。 –

+0

あります。実際のプログラムで。私の間違いはここにある。おっと – poh

+1

「レコード」の種類は何ですか?それにはいくつかの[vtable](https://en.wikipedia.org/wiki/Virtual_method_table)、あるいはいくつかの(内部または内部の)ポインタがありますか? **あなたのコードには[未定義の動作](https://en.wikipedia.org/wiki/Undefined_behavior)**がありますので、Linux上でクラッシュすることは幸運です(Windows上では動作すると思われます) .... –

答えて

1

Recordには、std::stringフィールドが含まれます。

stringには確かにポインタが含まれており、仮想関数を持つ内部データが含まれている可能性があります(隠しポインタであるvtable)。そのデータにはポインタがあります。 stringは、ではなく、であり、PODである(しかし、charの固定配列は、char name[48]; ....のようなフィールドである)。

undefined behaviorを持っているので、あなたのコードは、あなたが...ところで、ときに明らか(Windows上で動作するように「見える」と不運こと)がLinux上でcrashesその幸運「実行中」されている(たとえば、上あなたのプログラムの古いバージョン(または古いものや別のコンパイラやC++標準ライブラリでコンパイルされたものと同じもの)によって書き込まれたデータファイルを再び読み込むことはできません。

LinuxはASLRです。それはなぜあなたがsegmentation faultを持っているのか説明するかもしれません。ところで、と同じprocessのデータファイルを読み書きすると、Linuxがクラッシュしない可能性があります(これはあまり役に立ちません)。

詳細を理解するには、実装の詳細を掘り下げる必要があります。その必要はありません。

明らかに、serialization機械を実装する必要があります。次に(バイト単位で、endiannessと「単語サイズ」の問題とそのファイル形式は「独立」である必要があります)を指定してください(恐らく、EBNFの表記を使用しています)。次に、エレメンタリPOD型から始まるシリアル化ルーチンを実装します。または、シリアライズライブラリを使用します。ファイル形式とコードはポータブルでなければなりません(たとえば、Raspberry PiとLinux/PCの同じプログラムがデータファイルを交換できる必要があります)。

ところで、おそらくJSON,YAML(またはXML)を使用して、テキスト形式を使用する方が好きです。あるいは、SQLiteGDBMのようなライブラリも考えてください。あなたの場合、RecordはSQLiteテーブルの行やJSONオブジェクトに簡単にマップできます。おそらく、あなたはそれらを使用することが許可されている場合、教師に尋ねる必要があります....

関連する問題