【问题标题】:Segmentation Fault - linked lists (UNIX)分段错误 - 链表 (UNIX)
【发布时间】:2017-11-06 18:23:51
【问题描述】:

我试图了解为什么我会收到分段错误。

我有一个带有 prev 和 next 指针的链表“head”,我正在尝试删除列表中的特定节点。特定节点的地址由“ptr”保存。 我附上了一张显示调试器的图片, 以下代码给了我分段错误: (我只显示相关的内容)

void someFunc(char str[], int atmSN){


/*some code */ 

switch(ch){    /// ch is char

/* some code */

case 'Q':       
    if (ptr == head){                   // if ptr head of linked list
        head = head->next;
        if (head != NULL)
            head->prev = NULL;
    }
    else{
        ptr->prev->next = ptr->next;
        if (ptr->next != NULL)  // if ptr is not last
            ptr->next->prev = ptr->prev;
    }

    free(ptr);
break;

/*some code */ 

debugger

我的代码正在使用多线程,所以当当前线程试图删除它时,可能另一个线程正在写入特定节点。 在我的任务中,我还必须实现信号量,但这会给我们带来分段错误吗?

如果我错了,请纠正我:当我们尝试访问“不存在”的内存时会发生分段错误?

如果有人能启发我,我将不胜感激。

编辑:调试器信息:

 Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff5ff9700 (LWP 3350)]
0x00000000004011cb in operation (str=0x7ffff5ff8e00 "Q 1111 1111", atmSN=3)
    at hw4.c:175
175                     ptr->prev->next = ptr->next;

【问题讨论】:

  • switch(char ch) 我确定它不会编译。发布一个真实的minimal reproducible example。并且不要张贴图片,复制粘贴控制台的文字!
  • 整个代码有 500 行长,所以 char ch 只是为了显示 ch 是一个字符。如果它无法编译,我将无法向您发布配音器的屏幕截图。
  • 这并没有改变我所说的。
  • 调试器将很容易地提供分段错误发生的确切位置的信息。是在您尝试删除头部时发生,还是在其他情况下发生?
  • @Rom 也许是因为我们比你更了解我们需要什么来解决你的问题?你怎么相信我们可以知道你的真实程序有什么错误(或数百个错误)?你需要阅读 How to Ask AND minimal reproducible example

标签: c unix linked-list pthreads semaphore


【解决方案1】:

我的代码使用了多线程

多线程环境必须让您考虑锁定上下文,例如互斥锁或信号量。任何时候您有多个执行线程同时运行(超线程、多核或单核系统上的抢占式多线程),请考虑执行线程可以随时更改时刻保护逻辑由你来确保你不会把自己的脚炸飞。

因此,请考虑以下场景:

  • 您有两个线程,T1 和 T2。你有一个两节点的链表。
  • T1 调用你的代码并看到(ptr == head),然后继续前进。
  • 上下文切换!
  • T2 调用你的代码并看到(ptr == head),然后继续前进。
  • T2套head = head->next
  • T2 检查 if (head != NULL),发现它不是 NULL
  • 上下文切换!
  • T1套head = head->next

您认为 T1 分配给 head 的内容是什么?继续:

  • 上下文切换!
  • T2 分配head->prev = NULL。它只是取消了由T1 分配的head。你认为会发生什么?

想象一下这种对所有逻辑流程的上下文切换。你如何防范它?

这个问题的答案通常很好理解并且经常被问到(并且经常被回答)。您应该能够从这里找到您想要的答案。

【讨论】:

  • 如果没有 MCVE(@Stargateur 已经要求),我不可能明确地说出来。但是,是的,这是我最初的猜测。
  • @Rom:你知道链表代码在单线程环境下可以正常工作吗?如果没有,让它在单线程时正常工作。首先正确获取内存分配等。然后保护它以在多线程环境中使用,应用适当的互斥锁或其他同步控制操作(甚至可能是一个信号量,但我认为如果你小心的话,互斥锁可能就足够了)。您需要考虑需要多少并行度——您是否需要两个单独的线程才能同时访问同一个列表?如果你不这样做会更容易。
猜你喜欢
  • 2018-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多