【问题标题】:C - "Segmentation fault: 11" running programC - “Segmentation fault: 11”运行程序
【发布时间】:2015-01-07 18:27:08
【问题描述】:

这个程序在我运行时返回“Segmentation fault: 11”。编译器 (GCC) 不会返回任何错误或警告。

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

typedef struct {
  char day[3];
  char month[3];
  char year[5];
} DATA;

DATA *data;

int main()
{
  FILE *file;
  char line_buffer[BUFSIZ];

  if (!(file = fopen("file.dat", "rt")))
  { 
    printf ("Something went wrong while opening the file.\n");
  }
  else
  {
    int line_number = 0;

    while (fgets(line_buffer, sizeof(line_buffer), file))
    {
      ++line_number;

      if      (line_number == 1) { strncpy(data->day,   line_buffer, 2); }
      else if (line_number == 2) { strncpy(data->month, line_buffer, 2); }
      else if (line_number == 3) { strncpy(data->year,  line_buffer, 4); }
    }

    printf("Content: %s-%s-%s\n", data->day, data->month, data->year); 
  }
  return 0;
}

file.dat 的内容是:

12
08
1990

我已经用 GDB 调试过了,结果如下:

(gdb) run
Starting program: /Users/macuser/Desktop/Primitiva/Proyecto/a.out
Program received signal SIGSEGV, Segmentation fault.
0x00007fff949413a0 in _dispatch_queue_attrs () from /usr/lib/system/libdispatch.dylib

这是什么意思,我可以做些什么来解决这个问题?谢谢!

【问题讨论】:

    标签: c gcc segmentation-fault


    【解决方案1】:

    请注意,虽然使用malloc 可以工作,但对您来说这是不必要的额外工作,因为您以后不再需要使用data 结构时还必须调用free。但为此,您应该将变量设为 main() 的本地变量。

    这应该可以解决您的问题

    typedef struct {
    char day[3];
    char month[3];
    char year[5];
    } DATA;
    
    DATA data;
    /*  ^ no star here, because you don't need a pointer in your particular case */
    
    int main()
    {
    FILE *file;
    char line_buffer[BUFSIZ];
    
    if (!(file = fopen("file.dat", "rt")))
    {
        printf ("Something went wrong while opening the file.\n");
    }
    else
    {
        int line_number = 0;
    
        while (fgets(line_buffer, sizeof(line_buffer), file))
        {
        ++line_number;
    
        if      (line_number == 1) { strncpy(data.day,   line_buffer, 2); }
        else if (line_number == 2) { strncpy(data.month, line_buffer, 2); }
        else if (line_number == 3) { strncpy(data.year,  line_buffer, 4); }
        }
    
        printf("Content: %s-%s-%s\n", data.day, data.month, data.year);
    }
    return 0;
    }
    

    在这种特殊情况下,您不需要将data 声明为指针,如果您在正确理解动态内存分配之前不这样做会更好,而且data 变量不需要是全局的,你可以在main()函数中声明它。

    分段错误是由无效的指针解引用引起的,如果你想使用指针,那么你应该这样做

    typedef struct {
    char day[3];
    char month[3];
    char year[5];
    } DATA;
    
    int main()
    {
    FILE *file;
    char line_buffer[BUFSIZ];
    if (!(file = fopen("file.dat", "rt")))
    {
        printf ("Something went wrong while opening the file.\n");
    }
    else
    {
        int line_number = 0;
        DATA *data;
    
        /* 
         * here data is an invalid pointer, it points nowhere. 
         * to make it valid you need malloc
         */
        data = malloc(sizeof(*data));
        /* on failure, malloc returns NULL, for example when there is no more memory left in the system 
         * so one should check for the return value
         */
        if (data == NULL)
        {
            fclose(file);
            return -1;
        }
        /* now data is a valid pointer you can derefrence it */
    
        while (fgets(line_buffer, sizeof(line_buffer), file))
        {
        ++line_number;
    
        if      (line_number == 1) { strncpy(data->day,   line_buffer, 2); }
        else if (line_number == 2) { strncpy(data->month, line_buffer, 2); }
        else if (line_number == 3) { strncpy(data->year,  line_buffer, 4); }
        }
    
        printf("Content: %s-%s-%s\n", data->day, data->month, data->year);
        /* after you have finished using the pointer, call free */
        free(data);
    }
    return 0;
    }
    

    【讨论】:

    • 成功了!但是使用指针与不出现分段错误有什么区别?
    • @mariec 我不明白你的问题。
    • @mariec,我用程序的指针版本更新了答案,检查源代码,它有 cmets 让你知道它是如何工作的。
    • 是的,我只更改了指针,现在程序可以运行了,这是因为存在一些差异,指针超出了程序的内存限制。这只是好奇,我猜这会很困难哈哈
    • @mariec 这并不难,您只需要阅读它,您的代码中的内容称为未定义行为,因为您取消了对无效指针的引用。
    【解决方案2】:

    你忘记为你的结构分配内存

    DATA *data = malloc(sizeof(DATA));
    

    您应该在向指针写入内容之前为其分配内存。

    【讨论】:

    • 如果 OP 天真地将 malloc 放在他的源代码中,这将无法编译。
    • @MichaelWalz 对不起,我没有得到你。分配内存是他看到崩溃的原因
    • 没错,但你不能调用malloc(或任何其他函数)来初始化一个全局变量。
    • 迈克尔是对的。编译器返回:main.c:11:14: error: initializer element is not a compile-time constant DATA *data = malloc(sizeof(DATA)); ^~~~~~~~~~~~~~~~~~~~ 1 error generated.
    • 是的,是的。答案主要是建议分配内存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 2014-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多