簡體   English   中英

調用fread()C ++時出現分段錯誤

[英]Segmentation fault when calling fread() c++

我不明白我犯的錯誤。 我嘗試了很多,但無法讀取我的文件。 基本上,我將一個結構寫入名為0.txt / 1.txt / 2.txt ...的文件中,該文件基於帳戶amound。 我確實花了很多時間來解決我的問題,但我不明白如何解決以及為什么會收到錯誤消息。 另外,我在用我的開發代碼(使用dev c ++)編譯代碼時沒有問題,但是當我按“加載帳戶”按鈕時,出現錯誤“ Segmentation Faul t”(使用Windows 7)。 我注意到問題出在函數ladeAccounts() 中的fread()行上。 我的結構的名稱是“ iAccount”。 變量infoma是iAccount類型,而newAccount()中int anzahl類型的“現有帳戶數”決定了路徑。

iAccount看起來像這樣:

 struct iAccount
    {
        string ID;
        string password;
        int level;
    };

這是我將STRUCT寫入文件的方式:

void Account::newAccount(int anzahl, string username, string pw, int lvl)
    {
        iAccount neu;
        neu.ID = username;
        neu.password = pw;
        neu.level = lvl; 
        ss.str("");
        ss<<anzahl;
        s = ss.str();
        s = "Accounts/"+s+".txt";        
        f1 = fopen(s.c_str(), "w");
        fseek(f1, 0, SEEK_SET);
        fwrite(&infoma, sizeof(iAccount), 1, f1);        
        fclose(f1);             

    }

這就是我讀取文件的方式(調用fread()時出現錯誤

void Account::ladeAccount(int nummer)
    {
        stringstream sa;
        iAccount account_geladen;
        sa.str("");
        sa<<nummer;        
        s = sa.str();  
        s = "Accounts/"+s+".txt";     
        f2 = fopen(s.c_str(), "r"); 
        fseek(f2, 0, SEEK_SET);                  
        fread(&infoma, sizeof(infoma), 1, f2);               
        fclose(f2);                          

    }

謝謝您的幫助。 我不知道我的問題在哪里,正如我所說的,我正在尋找幾個小時。

編輯:我嘗試過打開文件(f2是真的!)。

編輯”: ERRNO = 0 !!!

看這里:

ostringstream Str;
Str << errno;   
infoma.ID = Str.str(); 

這樣做是為了在我的wxtextlabel中看到errno的結果。

原因

您很可能在NULL文件句柄上調用fread 因此,這里有兩個問題:

  1. 在您的代碼中(您不檢查fread成功或返回NULL值)
  2. 由於某些原因無法打開您的文件(對此,您應該進行調查...)

解釋

fopen (請參閱文檔 )可以出於不同的原因返回NULL句柄。 如果在調用fread之前未檢查句柄的有效性,則會出現分段錯誤。

提示

正如您在上面鏈接的官方文檔中所看到的那樣,在大多數庫實現中, errno變量可以幫助您提供有關故障的系統特定錯誤代碼。 這可以幫助您調試打開文件時的錯誤。

附帶問題

解決了我們代碼中的錯誤之后,您將遇到其他問題 正如人們(尤其是@Christophe)在其他答案中指出的那樣,您的代碼中存在結構性問題,因為您嘗試對非POD(又稱字符串)的文件對象進行序列化/反序列化。 由於字符串是復雜的對象,因此您無法直接對其進行序列化。

使用字符數組的方法將正常工作,因為可以按照您的編碼方式處理簡單類型。

因此,您可以使用std::string c_str()方法從字符串中獲取以null結尾的char數組,並將其存儲在文件中。

相反的操作則更加直接,因為您可以僅通過傳遞反序列化的char數組來初始化std :: string:

std::string str(the_array);

您有一個問題,因為您使用fread()加載二進制數據。 但這僅適用於普通舊數據(POD)對象。

它用較少的瑣碎對象給出災難性的結果,尤其是在這些對象的內部管理動態內存分配和/或指針的情況下,例如在字符串中就是這種情況。

順便說說:

如果您讀/寫二進制數據,則應該真正使用“ rb” /“ wb”作為fopen()模式。 如果不這樣做,則沒有必要進行seg.fault,但是在某些系統上您的數據可能不正確。

編輯:

抱歉,我的閱讀不夠好:如果它恰好發生在fread(),那么Alex提供的原因肯定會有所幫助。 但是,我留下了這個答案,因為一旦您解決了fopen()問題,如果嘗試使用已讀取的對象,則可能會遇到分段錯誤。 如果您沒有sizeof(iAccount) ,請查看sizeof(iAccount)並將其與字符串內容的大小進行比較。

編輯 if(f2)是true,所以我錯了,文件成功打開了嗎?

我發現該文件未打開/ fopen無法處理路徑,例如0.txt。 我也嘗試直接輸入路徑而不構建它(沒有stringstream等)。 我仍然有分割錯誤的問題。 我檢查了文件在“帳戶”文件夾中是否存在的所有內容。 我在同一文件夾中有另一個名為“ Accounts.txt”的文件,在讀取現有帳戶(也使用結構)的過程中沒有問題。 在那里,我什至不檢查fopen是否成功,但是無論如何我都將在稍后編寫文件打開檢查代碼。

用於讀/寫到Accounts / Accounts.txt的代碼是:

struct init{
    int anzahl_1;};
    init anzahl;
    FILE* f;
    static string ss = "Accounts/Accounts.txt";      
int account_anzahl1()
{ 

    f = fopen(ss.c_str(), "r");       
    fread(&anzahl, sizeof(init), 1, f); 
    fseek(f, 0, SEEK_END);      
    fclose(f);
    return anzahl.anzahl_1;


}
void account_anzahl_plus()
{
    anzahl.anzahl_1 = anzahl.anzahl_1 +1;     
    f = fopen(ss.c_str(), "w");
    fwrite(&anzahl, sizeof(init), 1, f);        
    fclose(f);    
}

那里我沒問題!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM