调用fread()c ++时出现分段错误

时间:2014-11-06 21:46:34

标签: c++ segmentation-fault fread

我不明白我犯的错误。  我尝试了很多,但我无法阅读我的文件。  基本上我将结构写入一个名为0.txt / 1.txt / 2.txt的文件...基于帐户amound。 我真的花了几个小时来解决我的问题,但我不明白我是如何解决的,以及为什么我会得到错误。  我在编译代码时也没有问题(使用dev c ++)但是当我按下加载帐户按钮时,我得到了错误“分段错误 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的结果。

3 个答案:

答案 0 :(得分:3)

原因

您最有可能在fread文件句柄上调用NULL。所以你有两个问题:

  1. 在您的代码中(您不检查fread是否成功或返回NULL值)
  2. 由于某些原因无法打开您的文件(此时,您应该调查......)
  3. 阐释

    fopen(请参阅documentation)可以出于不同原因返回NULL句柄。如果在调用fread之前未检查句柄的有效性,则会出现分段错误。

    提示

    正如您在上面链接的官方文档中所读到的,在大多数库实现中,errno变量可以帮助您在失败时提供系统特定的错误代码。这可以帮助您在打开文件时调试错误。

    附带问题

    一旦你在我们的代码中解决了这个错误,你就会有其他问题。正如人们(特别是@Christophe)在其他答案中所说的那样,你的代码中存在结构性问题,因为你试图序列化/反序列化你的文件对象非POD(也就是你的字符串)。由于字符串是复杂对象,因此无法直接对其进行序列化。

    使用字符数组的方法可以正常工作,因为简单类型可以按照编码的方式处理。

    出于这个原因,您可以使用std::string c_str()方法从字符串中获取空终止的字符数组,并将其存储在文件中。

    相反的操作更简单,因为你可以初始化一个std :: string,只需传递反序列化的字符数组:

    std::string str(the_array);
    

答案 1 :(得分:1)

您遇到问题,因为您使用fread()加载二进制数据。但这仅适用于普通旧数据(POD)对象。

它使用较少的简单对象来给出灾难性的结果,特别是如果这些对象的内部管理动态内存分配和/或指针就像这里的字符串一样。

顺便说一下:

如果您读/写二进制数据,您应该使用“rb”/“wb”作为fopen()的模式。如果不这样做,则不需要seg.fault,但在某些系统上您的数据可能不正确。

编辑:

抱歉,我读得不够好:如果它恰好发生在fread()provided by Alex肯定有帮助的原因。但是,我留下这个答案是因为只要您解决了fopen()问题,如果您尝试使用已阅读的对象,就可能会出现细分错误。如果您没有被定罪,请查看sizeof(iAccount)并将其与字符串内容的大小进行比较。

答案 2 :(得分:0)

修改 如果(f2)为真所以我错了,文件成功打开了吗?

我发现文件未打开/ fopen无法处理路径,例如0.txt。 此外,我试图直接进入路径而不构建它(没有stringstream等)。我还有分段故障的问题。我检查了文件夹Accounts中存在的所有文件。我还有一个名为&#34; Accounts.txt&#34;的文件。在同一个文件夹中,我在读取现有帐户(也使用结构)时没有任何问题。在那里,我甚至不检查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);    
}

我没有问题!