【问题标题】:segmentation fault when trying to copy integers from .txt file尝试从 .txt 文件复制整数时出现分段错误
【发布时间】:2018-04-06 06:45:07
【问题描述】:

因此,对于我的学校课程,我只需从以下格式的文本文件中读取整数列表,第一行表示整数的数量。然后对整数进行排序(它们在 txt 文件中未排序),然后求均值。我只是试图从我一直在使用的测试 .txt 文件中将整数读入数组。

9

1

3

2

4

...

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

int amtValues;
int *values;

float find_median (int* values){
    if(amtValues%2==0){
        return ((values[amtValues/2] + values[amtValues/2 -1]) /2.0);
    }
    else
        return values[amtValues/2];
}

int main(int argc, char **argv){

//open the file, copy the data from the file, and determine the number of values
    //open the filestream
    FILE* fp = fopen(argv[1], "r");
    if(!fp){
        printf("error reading file\n");
        return 1;
    }

    //determine the number of values
    char *lineOne;
    
    if(fgets(lineOne, 80, fp)!=1)
        puts (lineOne);
    lineOne++;
    amtValues = atoi(lineOne);
    printf("\nThe amount of values is: %d\n",amtValues);

    /*allocate memory for values array, and copy the values from file.*/
    values = (int*)malloc(amtValues*sizeof(int));
    int i=0;

    while(!feof(fp)){
        int curNum;
        fscanf(fp, "%d", &curNum);
        values[i] = curNum;
        i++;
    }
    fclose(fp);

    for(i=0; i<amtValues; i++)
        printf("\n%d");
}

这就是我目前要做的事情,我收到一个错误,说segmentationFault(core Dumped)。我是 C 新手,所以我真的不确定这意味着什么。

【问题讨论】:

标签: c file dynamic-arrays


【解决方案1】:

我没有检查你的整个代码,但这里导致分段错误:

//determine the number of values
char *lineOne;

if(fgets(lineOne, 80, fp)!=1)
    puts (lineOne);

您需要有lineOne 的内存。只有一个指针并不意味着你的缓冲区有内存,你需要在堆或堆栈上分配它。试试这样:

char lineOne[81]; // allocation on stack

char *lineOne = malloc(sizeof(*lineone) * 81); // allocate on heap

【讨论】:

  • 可以使用malloc
  • @BasileStarynkevitch 我已经写了你需要在堆或堆栈上分配它。该行只是一个示例,但我也添加了它。
【解决方案2】:

我收到一条错误消息:分段错误(核心转储)

segmentation fault 实际上是一些 undefined behavior (UB),这意味着您的程序是 buggy,因为计算机正在取消引用一些无效的 memory address(在 @987654325 之外@你的process)。

(我猜您使用的是 Linux 或其他 POSIX 系统,但应该在您的问题中提及)

core dump(在 Linux 上,请参阅 core(5) 了解详细信息)是一个文件 - 通常名为 core - 描述故障进程的状态(当故障发生时,请参阅 signal(7)),特别是它的虚拟地址空间。您可以use gdb 调试器来调试核心转储。您还可以禁用核心转储(但最好不要,它们非常有用),例如使用ulimit -c bash 内置(或setrlimit(2) 系统调用)。

但是,并非所有未定义的行为都会产生这样的错误。你很幸运能得到一个。并且可能发生(例如,由于 ASLR)相同的错误 executable 的另一次运行不会核心转储或段错误(但会出现一些更糟糕的行为)。

在实践中:

  • 编译时包含所有警告和调试信息gcc -Wall -Wextra -gGCC。改进您的代码以完全不收到警告(在您的情况下,您的代码会收到一些警告)。

  • 阅读文档,尤其是您的 compiler 和您正在使用的 every 函数(例如,您错误地使用了 fgets:它永远不会给出 1)。以后,你甚至可以阅读 C11 标准n1570

  • 了解如何通过 use the gdb debugger 了解错误程序的行为。这是获得的一项基本技能。你应该有tests

  • 了解更多关于 UB,并成为其中的 scared。最糟糕的 UB 是显然不(总是)给出错误的那个。 valgrind 之类的工具很有帮助。

也许你想使用getline(3)。见this。也许你可以有一个flexible array member,比如herereason,还有一些abstract data type


还要注意Halting Problem 及其undecidability

PS。所有开发人员都会制造错误。找到它们是具有挑战性的,并且可能很有趣。但是编程是difficult

【讨论】:

  • 他的分段错误有一个明显的来源。 lineOne 没有像我在回复中提到的那样分配。
  • 是的,但是 OP 需要学习如何调试他的程序。如果我们做所有的调试,他永远学不会
  • 如果您认为我是对的,请提供编辑建议。我认为最好提到分段错误通常是由无效的访问内存引起的(至少从我的经历来看)。所以首先检查无效的内存访问是很重要的,比如指针。
  • 我会说最好确保指针在取消引用时有效。如何做到这一点留给读者作为练习。 :-) :-)
猜你喜欢
  • 1970-01-01
  • 2018-06-27
  • 2021-12-19
  • 1970-01-01
  • 2018-05-01
  • 2017-04-18
  • 2015-08-27
  • 2018-05-09
  • 1970-01-01
相关资源
最近更新 更多