【问题标题】:Segmentation fault when different OS不同操作系统时的分段错误
【发布时间】:2013-04-20 18:57:25
【问题描述】:

我有一个 C 项目,我对 C 和 linux 环境还很陌生。

我正在开发具有以下系统信息的 linux 发行版

Linux bt 3.2.6 #1 SMP Fri Feb 17 10:34:20 EST 2012 x86_64 GNU/Linux

用gcc编译后,在上述操作系统上,我得到了等待的结果。

在将我的项目提交给教授之前,我曾想过尝试使用以下系统信息在另一个 linux 发行版上编译和执行程序

Linux feistyFawn 2.6.20-15-generic #2 SMP Sun Apr 15 07:36:31 UTC 2007 i686 GNU/Linux

我在这个下遇到分段错误。 来说明输出控制台。这是图片。

作品

失败

我不知道现在该怎么办。


代码

调用此函数会导致另一个操作系统出现分段错误。

fileInEvenements(listEvents, 'A', time, queueId);

它的作用是将名为 A 的事件归档到队列结构 listEvents 中。

及其定义

void fileInEvenements(eventStructure *listEvents, char eventType, int time_exec, int id_queue)
{
    Event *newEvent = malloc(sizeof(*newEvent));
    if (newEvent == NULL || listEvents == NULL){
        exit(EXIT_FAILURE);
    }

    newEvent->type = eventType;
    newEvent->execution_time = time_exec;
    newEvent->id = id_queue;
    if (listEvents->firstEvent != NULL)
    {
        // the list contains at least one event, go to the end of list 
        Event *evCurrent =  listEvents->firstEvent;
        while (evCurrent->next != NULL)
        {
            evCurrent = evCurrent->next;
        }
        evCurrent->next = newEvent;
    }
    else // the list contains no event, new event becomes first event
    {
        listEvents->firstEvent = newEvent;
    }

}

【问题讨论】:

  • 请显示导致此错误的代码。
  • 您的代码在两台计算机上(可能)都是错误的。当它没有在其中一个上崩溃时,你就很不走运了。
  • 使用调试标志编译并使用 gdb 分析

标签: c segmentation-fault portability


【解决方案1】:

当您在链接列表中创建新条目时,您会尝试通过从头部开始并迭代列表直到在evCurrent->next 中找到NULL 来将其附加到列表中。当您确实找到 NULL 时,您将停止迭代列表,然后通过 evCurrent->next = newEvent; 将 newEvent 分配为列表中的下一个条目 - 当然,如果链接列表中没有条目,您通过 listEvents->firstEvent = newEvent; 将新条目设置为列表的头部

但是,您绝不会初始化newEvent->next 的值。请注意,malloc() 不会初始化它返回的内存块。它只是分配一个块并将其返回给您。请参阅此处的文档http://www.cplusplus.com/reference/cstdlib/malloc/

关键是这个……

新分配的内存块的内容没有初始化, 剩下不确定的值。

因此,newEvent->next 实际上是一个随机值。因此,您的代码会进入随机内存漫游,因为您指望它是 NULL 来终止链表。

我建议你改用calloc()。

Evenement *newEvent = calloc( 1, sizeof(*nvEvent) );

否则,请确保在创建 next 元素时将其值初始化为 NULL。

【讨论】:

  • 我不确定我是否真的同意你的看法。 evActuel->suivant 假设获取下一个链表的地址,因此初始化它会破坏结构的链接。不是吗?
  • @afiqjohari:你必须确保suivant 成员指向某个地方——一个有效的结构或NULL。使用valgrind;它也应该为您发现问题。
  • @afiqjohari -- 想想看……你从listEvents->firstEvent 设置为NULL 开始。然后你创建你的第一个 newEvent 并将它分配给 listEvents->firstEvent 但你还没有将 next 初始化为 NULL ......这是一些随机值。现在你去创建一个新的newEvent 并测试listEvents->firstEvent 并发现它不是NULL 所以你检查listEvents->firstEvent->next 看看它是否是NULL——但它是一些除此之外的随机值。 .. 发生什么了?只需更改我建议的calloc(),问题就会消失。
  • 是的,我刚刚意识到这一点!
【解决方案2】:

添加一行:

newEvent->next = NULL;

使用未初始化的字段是错误的。

或者,您可以在以下情况下使用:

newEvent = calloc(sizeof(*newEvent), 1); // instead of malloc

或者

memset(newEvent, 0, sizeof(*newEvent)); // set all fields to 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-19
    • 2022-01-13
    • 1970-01-01
    • 2017-03-06
    • 2014-10-22
    • 1970-01-01
    • 2021-04-06
    • 2023-03-22
    相关资源
    最近更新 更多