fopen c 上的段错误

Segfault on fopen c

在下面的代码中,我得到了 seg.fault,我不知道为什么会这样,因为我认为我将正确的参数传递给了 fopen

正在编译:

gcc -o testloadfile testloadfile.c

运行 次尝试:

第一次尝试

./testloadfile "correctme.txt"

第二次尝试

 sudo ./testloadfile correctme.txt 

testloadfile.c 的同一文件夹中,我有一个名为 correctme.txt

.txt

代码如下

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

static void load_array(const char* file_name){
  char *read_sentence;
  char buffer[2048];
  char a[100][100];
  int buf_size = 2048;
  FILE *fp;
  int j = 0, c = 0;

  printf("\nLoading data from file...\n");
  printf("%s \n", file_name); //prints correctme.txt  
  fp = fopen(file_name,"r"); //error happens here
  printf("This line won't be printed \n"); 
  if(fp == NULL){
    fprintf(stderr,"main: unable to open the file");
    exit(EXIT_FAILURE);
  }

 read_sentence = malloc((2048+1)*sizeof(char));

 read_sentence = fgets(buffer,buf_size,fp);

  for(int i = 0; i < strlen(read_sentence); i++) {
    a[j][c++] = read_sentence[i];
    if(read_sentence[i] == ' ' || read_sentence[i] == '.' || read_sentence[i] == ',') {
        j++;
        c = 0;
        continue;
    }   
  }

  free(read_sentence);

  for(int i = 0; i < 100; i++) 
    printf("%s\n", a[i]);

  fclose(fp);
  printf("\nData loaded\n");
}

int main(int argc, char const *argv[]) {
  if(argc < 2) {
    printf("Usage: ordered_array_main <file_name>\n");
    exit(EXIT_FAILURE);
  }

  load_array(argv[1]);

}

这是提到的文件夹

这是 gcc -g testloadfile testloadfile.c

的输出
testloadfile: In function `_fini':
(.fini+0x0): multiple definition of `_fini'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o:(.fini+0x0): first defined here
testloadfile: In function `data_start':
(.data+0x0): multiple definition of `__data_start'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.data+0x0): first defined here
testloadfile: In function `data_start':
(.data+0x8): multiple definition of `__dso_handle'
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o:(.data+0x0): first defined here
testloadfile:(.rodata+0x0): multiple definition of `_IO_stdin_used'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.rodata.cst4+0x0): first defined here
testloadfile: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.text+0x0): first defined here
testloadfile: In function `_init':
(.init+0x0): multiple definition of `_init'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o:(.init+0x0): first defined here
/tmp/cc0ye2Ms.o: In function `main':
/home/zenoraiser/Scrivania/Università/Secondo Anno/Algoritmi/1718/LAB/Progetto/Esercizio2/testloadfile.c:42: multiple definition of `main'
testloadfile:(.text+0x346): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o:(.tm_clone_table+0x0): multiple definition of `__TMC_END__'
testloadfile:(.data+0x10): first defined here
/usr/bin/ld: error in testloadfile(.eh_frame); no .eh_frame_hdr table will be created.
collect2: error: ld returned 1 exit status

然后我做了ulimit -c unlimited

之后我运行程序./testloadfile "correctme.txt"

最后我用了gdb ./bynary core,这是输出

GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
./bynary: No such file or directory.
/home/zenoraiser/Scrivania/Università/Secondo Anno/Algoritmi/1718/LAB/Progetto/Esercizio2/core: No such file or directory.

(抱歉,稍后我会尝试了解如何使用最后一个命令)

实际的段错误可能在这条线上:

 free(read_sentence);

重要的是要记住 printf() 将输出发送到缓冲的 stdout。因此,如果发生段错误,您发送给它的东西不一定会被打印出来。

至于段错误本身,让我们在这里看一下这些行:

read_sentence = malloc((2048+1)*sizeof(char));

read_sentence = fgets(buffer,buf_size,fp);

看起来您认为您正在分配 read_sentence,然后将从 fp 读取的数据放入其中(实际上代码会像这样发生),但事实并非如此。

相反,您将数据读入buffer,然后将read_sentence设置为的地址buffer

然后你做你的操作,我们回到我指出的第一行:

free(read_sentence);

这不是释放在上面的 malloc() 调用中分配的内存,而是释放堆栈上的 buffer,因此不能 free()-ed。另外请注意,您最初为 read_sentence 分配的内存现已泄漏,您将无法释放它。

最好的解决方案是将 read_sentence(连同 malloc()free() 对)放在一起,只在 buffer 中进行操作.