C中的文件读取,随机错误

时间:2011-04-05 09:51:18

标签: c

到目前为止,感谢大家的意见和建议!

此外:

经过测试和进一步调查后,似乎对FileReader的单独调用成功。但是多次调用FileReader(这些可能是FileReader的单独版本)会导致问题发生。

结束添加

您好,

我有一个非常不寻常的问题[请完整阅读:重要的是](Code :: Blocks编译器,Windows Vista Home)[没有可复制代码]和C文件读取功能(fread,fgetc)。现在,通常,文件读取功能正确地将数据加载到自分配和自解除分配的字符串(并且它不是字符串的问题),但这是奇怪的(以及量子物理学适合的地方):

错误捕获语句报告EOF发生得太早(IE正在加载的文本文件开头的注释部分内)。打印出字符串[加载后]确实报告确实太短(24个字符)(但它有足够的空间来容纳它[~400]并且没有分配问题)。 fgetc循环迭代器报告它终止于24(文件长度大约为300个字符)并带有EOF:这就是它的重要性

暂时检查Read-> _base报告整个(~300)字符被加载 - 24处没有EOF。困惑,[给它是一个fgetc循环]我添加了一个printf来显示每个字符[作为%d所以我可以在每一步发现-1 EOF]所以我可以看到它正在做什么,并修改它所以它是一个单一的字符。它循环很好,达到~300而不是24 - 但稍后随机冻结。但是,当我删除printf时,它再次终止于24并被错误捕获的声明所捕获。

摘要: 所以,基本上:我有一个受量子物理学中“观察者效应”影响的错误:当我试图观察我从fgetc通过printf得到的字符时,问题(早期EOF终止于24)消失了,但是当我停止查看它,错误捕获语句报告提前终止。

更奇怪的是,这不是第一次发生。 Fread有类似的问题,我无法找出原因,并将其替换为fgetc循环。

[无法真正提供代码,因为代码库的大小为5个标题]。

段:

int X = 0; 
int C = 0; 
int I = 0;

while(Copy.Array[X] != EOF)
{
    //Copy.Array[X] = fgetc(Read);
    C = fgetc(Read);
    Copy.Array[X] = C;
    printf("%d %c\n",C,C); //Remove/add this as necessary
    if(C == EOF){break;}
    X++;
}

侧注:将其分解为最简单的格式不会重现错误。

5 个答案:

答案 0 :(得分:5)

这是本书中最古老的错误,有点像。

您不能使用char类型的变量来读取字符(!),因为EOF常量不适合。

你需要:

int C;

此外,while条件看起来很可怕,你在循环中递增X,然后检查(新)位置,是否正确初始化?在开始循环之前,您没有显示Copy.Array的设置方式。

我建议完全删除它,这是非常奇怪的代码。

事实上,我不明白为什么你要循环阅读单个字符,为什么不只是使用fread()来阅读你需要的内容呢?

答案 1 :(得分:1)

首先,展开的答案是一个有效的观点,虽然我不确定它是否能解释你所看到的问题。

其次,

printf("%d %c\n",C,C); //Remove/add this as necessary

可能是个问题。 %d%c格式说明符期望int为参数,您只传递char。根据您的编译器,这可能意味着它们太小了。


这就是我认为问题所在:

你是如何分配Copy.Array的?在开始之前,您是否确保其所有元素都归零?如果你malloc它(malloc只是留下它返回的内存中的垃圾)并且一个元素碰巧包含0xFF,你的循环将提前退出,因为你的while条件测试Copy.Array [X]之前你已经放置那个位置的角色。

这是少数情况之一,我允许自己将一个赋值放在一个条件中因为模式

int c;
while ((c = fgetc(fileStream)) != EOF)
{
    doSomethingWithC(c);
}

真的很常见


修改

请阅读您的“另外”评论。我认为你很可能超出输出缓冲区。我认为您应该将代码更改为:

    int X = 0; int C = 0; int I = 0;
    while(X < arraySize && (C = fgetc(Read)) != EOF)
    {
        Copy.Array[X] = C;
        printf("%d %c\n", (int)C, (int)C);
        X++;
    }
    printf("\n");

请注意,我假设您有一个名为arraySize的变量,该变量设置为您可以写入数组但不会超出它的字符数。另请注意,我没有将EOF写入您的阵列。

答案 2 :(得分:0)

您可能正在进行一些堆损坏。没有看到代码就无法说出来。

答案 3 :(得分:0)

不确定这是否是您的错误,但是此代码:

C = fgetc(Read);
Copy.Array[X] = C;
if(C == EOF){break;}

表示您要将EOF值添加到数组中 - 我很确定您不希望这样做,尤其是因为您的数组可能是charEOFint,所以你实际上会在那里得到一些其他值(这可能会破坏以后的循环等)。

相反,我建议您更改顺序,以便C只有在您知道它不是EOF后才会放入数组中:

C = fgetc(Read);
if(C == EOF){break;}
Copy.Array[X] = C;

答案 4 :(得分:0)

虽然这不是我称之为'完整'的答案(因为bug仍然存在),但这确实解决了'观察者效应'元素:我发现,由于某种原因,printf以某种方式'修复'代码并且使用std :: cout似乎(好吧,我不能说'修复'问题)阻止观察者效应的发生。也就是说,使用std :: cout而不是printf(因为printf是观察者效果的起源)。

在我看来,printf在较低级别的内存中执行某些操作,似乎部分纠正了内存分配错误。