【问题标题】:Segmentation fault in malloc while using linked list使用链表时 malloc 中的分段错误
【发布时间】:2017-11-21 08:25:09
【问题描述】:

程序从文件中读取数据,将所需数据存储在一些变量中,然后将其压入堆栈。这是输入文件的一小部分,文件包含重复多次的数据(每个数据块中变量的值发生变化)。

----------------------------------------------------------------------- 
Timestamp (Wed Mar 29 20:44:08 2017) 
[1] Received msg from node <00116 / fc:c2:3d:00:00:10:ab:35> 
RSSI -6 dBm / LQI 22
+[Node_Voltage]  <2.963000 Volts> 
+[P_MS5637]      <896 mbar> 
+[NTC_THERM (Murata NXFT15XH103)]    <27.755314 deg C> 
+[Temp_LM75B]    <27.620001 Deg C> 
+[RH_CC2D33S]    <33.000000 %> 
+[Temp_CC2D33S]  <27.000000 Deg C> 

存储的数据被推送到发生分段错误的堆栈中。故障发生后,程序只能存储一个堆栈。

void create(stack **head){
    *head=NULL;
}

void copy_string(char arr[],char arr2[]){
    int i=0;

    for(i=0;i<strlen(arr2);i++){
        arr[i] = arr2[i];
    }
}

stack demo;          
stack *tracker;

// **head is used since this is an ADT, i've not pasted the code in source file here 

void push(stack **head,char date[],char time[],char month[],char year[],float pressure,float temprature1,float temprature2,float rel_humid,float node_voltage){
    stack *temp = malloc(sizeof(demo));   

    temp->pressure = pressure;
    temp->temprature1 = temprature1;
    temp->temprature2 = temprature2;
    temp->rel_humid = rel_humid;
    temp->node_voltage = node_voltage;

    printf("Inside push function\n");

    copy_string(temp->date, date);
    copy_string(temp->time, time);
    copy_string(temp->month, month);
    copy_string(temp->year, year);


    if(*head==NULL){
        temp->next = NULL;
        *head = temp;
        tracker = temp;
    }
    else{
        tracker->next = temp;
        tracker = tracker->next;
        tracker->next = NULL;
    }

    free(temp);     //on removing this, program runs infinitely instead of giving segmentation fault

    printf("%s %s %f %f ",tracker->date,tracker->year,tracker->pressure,tracker->node_voltage);
}

使用 gdb(GNU Debugger) 我得到了这个错误信息 -

Inside push function

29 2017) 896.000000 2.963000 Done!!

Program received signal SIGSEGV, Segmentation fault.
__GI___libc_free (mem=0x11f1) at malloc.c:2949
2949    malloc.c: No such file or directory.

已解决:整个问题的原因是 free(temp),它需要从上面的代码和主文件中删除,运行一次代码后文件指针被错误关闭,因此无限循环正在运行同时再次输入。

【问题讨论】:

  • 创建Minimal, Complete, and Verifiable Example 时,重要的是不要忘记完成 部分。 main 函数在哪里?你如何使用你展示的这些功能?你给他们什么? stack 是什么? create 函数并没有真正创建 任何东西?为什么你有自己的copy_string 而不是标准的strcpy?当您在调试器中发现崩溃时,请始终检查调用堆栈(使用 GDB 中的bt 命令),以便您知道它发生在您的代码中的什么位置。
  • 删除free(temp);
  • free(temp) 的问题在于您释放了刚刚为添加到堆栈中的节点分配的内存。当您将节点链接到列表中时,您只链接到malloc 分配的内存,您不会由此创建新的stack 结构。当您调用free(temp) 时,您会在列表中留下一个指向未分配内存的杂散指针,当您尝试访问该内存时会导致未定义行为。如果这是崩溃的原因,我们只能推测。
  • 再一次,请learn how to use GDB!如何用the bt command查看函数调用栈。
  • 要完整回答这个问题,我们需要:1.stack的定义,2.调用push() 的函数。 1 是了解堆是如何被破坏的必要条件。 2 是理解为什么你的程序有无限循环的必要条件。

标签: c linked-list stack malloc


【解决方案1】:

你在free()ing 然后在*head==NULL 访问同一个对象。 查看下面标有**** 的行。

if(*head==NULL){
    temp->next = NULL;
    *head = temp;
    tracker = temp;//**** temp is assigned to tracker. They point to the same place.
}
else{
    //...
}

free(temp);     //**** temp is free()d but remember tracker==temp..

//**** Now you output tracker but the object at this location was just freed.
printf("%s %s %f %f ",tracker->date,tracker->year,tracker->pressure,tracker->node_voltage);

所以删除 free(temp) 它在完全错误的地方,但你没有提供足够的代码来说明它的去向。

“无限循环”是其他一些错误,但您没有提供足够的代码来识别它。

还要注意else 部分没有多大意义:

    tracker->next = temp;
    tracker = tracker->next;
    tracker->next = NULL;

目前尚不清楚tracker 的内容,但假设它是有效的,这相当于:

    tracker = temp;
    temp->next = NULL;

【讨论】:

  • 这不是完整的答案。请记住,崩溃发生在free()。我认为其他东西正在破坏堆。
  • @JeremyP 如果这不是唯一的错误,我不会感到惊讶。这段代码有很多问题,但这肯定是一个致命的问题。他们还将free() 的对象分配给*head,这将在以后造成更多麻烦,包括可能的堆损坏。代码片段不足以实际“修复”这个程序。
  • 请看上面的cmets,问题已经解决了
  • @Masquerade 字符串终止符? push() 的问题仍然是致命的。
猜你喜欢
  • 1970-01-01
  • 2017-06-06
  • 1970-01-01
  • 1970-01-01
  • 2021-11-17
  • 1970-01-01
  • 1970-01-01
  • 2014-03-29
相关资源
最近更新 更多