为什么这个C代码给我一个总线错误?

时间:2012-07-30 18:29:02

标签: c arrays function bus-error

像往常一样,我在这里阅读了不少帖子。我发现有关总线错误的特定有用帖子,请参阅here。我的问题是,我无法理解为什么我的特定代码给了我一个错误。

我的代码是尝试自学C.这是我学习Java时所做的游戏的修改。我的游戏的目标是采取一个巨大的5049 x 1文字文件。随机选择一个单词,混淆它并尝试猜测它。我知道如何做到这一切。所以无论如何,文本文件的每一行都包含一个单词:

   5049
   must
   lean 
   better 
   program 
   now
   ...

所以,我在C中创建了一个字符串数组,试图读取这个字符串数组并将其放入C.我没有做任何其他事情。一旦我将文件放入C,其余的应该很容易。更奇怪的是,它符合它。当我使用./blah命令运行它时出现问题。

我得到的错误很简单。它说:

zsh: bus error ./blah

我的代码如下。我怀疑它可能与内存或溢出缓冲区有关,但这是完全不科学和直觉。所以我的问题很简单,为什么这个C代码给我这个总线错误消息?

#include<stdio.h>
#include<stdlib.h>

//Preprocessed Functions 
void jumblegame();
void readFile(char* [], int);


int main(int argc, char* argv[])
{
    jumblegame();

}

void jumblegame()
{
    //Load File 
        int x = 5049; //Rows
        int y = 256; //Colums
        char* words[x]; 
        readFile(words,x);

    //Define score variables 
        int totalScore = 0;
        int currentScore = 0; 

   //Repeatedly pick a random work, randomly jumble it, and let the user guess what it is

}

void readFile(char* array[5049], int x) 
{
    char line[256]; //This is to to grab each string in the file and put it in a line. 
    FILE *file;
    file = fopen("words.txt","r");

    //Check to make sure file can open 
    if(file == NULL)
    {
        printf("Error: File does not open.");
        exit(1);
    }
    //Otherwise, read file into array  
    else
    {
        while(!feof(file))//The file will loop until end of file
        {
           if((fgets(line,256,file))!= NULL)//If the line isn't empty
           {
               array[x] = fgets(line,256,file);//store string in line x of array 
               x++; //Increment to the next line 
           }    
        }
    }

}

6 个答案:

答案 0 :(得分:3)

这一行存在一些问题:

array[x] = fgets(line,256,file);//store string in line x of array 
  • 您已经在前一个if语句的条件下阅读了该行:您要操作的当前行在缓冲区中已经已经了您使用fgets获取下一行行。

  • 您每次尝试分配到同一个数组插槽时:相反,您需要为数组索引保留一个单独的变量,每次循环都会增加。

  • 最后,您尝试使用=复制字符串。这只会复制引用,它不会创建字符串的新副本。因此,数组的每个元素都将指向同一个缓冲区:line,它将超出范围,并在函数退出时变为无效。要使用字符串填充array,您需要为数组创建每个字符串的副本:使用malloc为每个新字符串分配空间,然后使用strncpy复制每个line x 1}}到你的新字符串。或者,如果您可以使用strdup,则需要为您分配空间。

但我怀疑这是导致总线错误的原因:您将数组 size 作为array[x]传入,并且在循环中,您将分配给{{ 1}}。这个问题是array[x]不属于数组,数组只有0(x - 1)的可用索引。

答案 1 :(得分:2)

您传递的值为5049。第一次该行

array[x] = ... 

执行,它正在访问一个不存在的数组位置。

看起来你正在学习C.太棒了!您需要掌握的技能是基本的调试器使用。在这种情况下,如果使用

编译程序
gcc -g myprogram.c -o myprogram

然后用

运行它
gdb ./myprogram

(我假设Linux),您将获得一个堆栈转储,显示发生总线错误的行。这应该足以帮助您自己找出错误,从长远来看,这比询问其他错误要好得多。

调试器有许多其他方法可用,但这在列表中很高。它为您提供了一个运行程序的窗口。

答案 2 :(得分:0)

您将行存储在行缓冲区中,该行缓冲区在readFile函数内定义,并在arary中存储指向它的指针。有两个问题:每次读取新字符串并且缓冲区在堆栈中时,您将覆盖该值,并且在函数返回后无效。

答案 3 :(得分:0)

char* array[5049], int x
array[x] = fgets(line,256,file)

您分配给array [x],这是一个长度为1的内存位置,您指定一个指针(4个字节)。

另一方面,你读了256次256字节,你就失去了前256位。

但是最大的错误是你把最后的条件!feof(),它检查字符串数组的限制是否溢出。

答案 4 :(得分:0)

你至少有一些问题:

  • array[x] = fgets(line,256,file)

    这会将line的地址存储到每个数组元素中。当line返回时,readFile()不再有效,因此您将拥有一系列无用的指针。即使line具有更长的生命周期,让所有数组元素具有相同的指针也是没有用的(它们每个只指向最后一次写入缓冲区的内容)

  • while(!feof(file))

    这是一个用于读取文件的反模式。请参阅http://c-faq.com/stdio/feof.html"Using feof() incorrectly"。这个反模式可能会导致您的程序循环超出读取文件时的预期。

  • 你分配数组来保存5049个指针,但你只需读取文件中的多少 - 没有检查你是否读取了预期的数字或防止读取太多。您应该考虑在读取文件时动态分配数组,或者考虑使用一种机制来确保您读取正确数量的数据(不是太少而不是太多),并在错误时处理错误。

答案 5 :(得分:-1)

我怀疑问题出在(fgets(line,256,file))!=NULL)。阅读文件的更好方法是使用fread()(请参阅http://www.cplusplus.com/reference/clibrary/cstdio/fread/)。指定FILE*(C中的文件流),缓冲区大小和缓冲区。例程返回读取的字节数。如果返回值为零,则表示已达到EOF。

char buff [256]; 
fread (file, sizeof(char), 256, buff);