【问题标题】:SIGSEGV errors that just showed, worked fine before刚刚显示的 SIGSEGV 错误,之前运行良好
【发布时间】:2011-12-25 02:40:57
【问题描述】:

我不知道我的代码发生了什么,我有一个通用链表 昨天它就像一个魅力,我没有以任何方式改变它,但不知何故 现在,当列表的 getter 和 setter 尝试到达列表的字段或其节点时,我得到了那些 SIGSEGV 错误并且我的代码终止了,这就是我的 list.c 文件的相关部分:

struct LinkedList
{
    Node m_head;
    Node m_tail;
    int m_numOfElements;
};


List CreateLinkedList()
{

    List list = (List)malloc(sizeof(struct LinkedList));

    if (list == NULL)
    {
        printf("memory alloc failed\n");
        return NULL;
    }
    list->m_head = NULL;
    list->m_tail = NULL;
    list->m_numOfElements = 0;

    return list;
}

我在 ilst.c 文件中包含的 list.h 文件中也有该 typedef:

typedef struct LinkedList* List;

调试了几个小时后,我注意到在创建列表时头部和尾部没有得到 NULL 值,它们仍然有一些地址而不是零,它也发生在创建节点和此列表的其他用途中,为什么会这样?我的堆损坏了?为什么它不应该为这些字段分配 null ?!无论如何请记住它运作良好,我不知道是什么改变了它..谢谢!

编辑:

这是我的 node.c 文件中的 AddNode 函数:

int AddNode(List list, Element data)
{
    Node newNode;
    //there is no linked list to add the element to
    if(list == NULL)
        return -1;

    newNode = CreateNewNode(data);

    if(newNode == NULL)
    {
        printf("Failed allocating memory\n");
        return 1;
    }

    //Empty Linked List
    if (list->m_head == NULL)
    {
        list->m_tail = list->m_head = newNode;
    }
    else
    {
        SetNext(list->m_tail,newNode);
        SetPrev(newNode, list->m_tail);
        list->m_tail = newNode;
    }
    //increase num of elements
    list->m_numOfElements++;
    return 1;
}

在第一次调用 AddNode 时,当列表为空并且我正在添加第一个元素时 它跳过空链表的 if 并转到之后的 else,它不应该。什么可以在我的应用代码中发生这种情况?

编辑 2:

好的,这是我使用列表之前唯一的结构分配:

struct Server_t
{
    List UsersList;
};

Result CreateServer(Server thisServer)
{
    if (thisServer = (Server)malloc(sizeof(struct Server_t)))
    {
        thisServer->UsersList = CreateLinkedList();
        return Success;
    }
    return Failed;
}

主要这样称呼它:

Server mainFacebookServer;
CreateServer(mainFacebookServer);

Result 是枚举,Server 是指向该结构的指针。

编辑 3:

Node CreateNewNode(Element data)
{
    Node newNode = (Node)malloc(sizeof(struct NODE));

    newNode->m_next = NULL;
    newNode->m_prev = NULL;
    newNode->m_data = data;
    return newNode;
}

二传手是:

void SetNext(Node node, Node toSet)
{
    node->m_next = toSet;
}
void SetPrev(Node node, Node toSet)
{
    node->m_prev = toSet;
}

【问题讨论】:

  • 只要检查返回值,正确使用这段代码应该没问题。问题不在这里——它在其他一些代码中。您最好向我们展示足够多的其余代码以便能够运行它。你在 Linux 上吗?你有valgrind 可用吗?如果是这样,请使用它。
  • 我在 Windows 中运行 ubuntu 11.10 的 VMWare 播放器上...我不知道我的代码的其他相关部分应该放在这里,列表初始化不能正常工作..
  • 您应该能够找到 Ubuntu 的 valgrind。用它。 CreateNewNode() 的代码可能是相关的; SetNext()SetPrev() 的代码可能是相关的。你的CreateServer() 函数无法在Serverstruct Server_t 之间做出决定——是你没有显示的typedef Server_t *Server; 吗? (就我个人而言,我尽量避免使用隐藏指针的 typedef。)
  • 我添加了这些函数,我无法在 .h 文件中公开我的结构,那么我应该如何使用指向这些结构的指针?

标签: list null segmentation-fault


【解决方案1】:

这段代码并没有像你想象的那样做:

Result CreateServer(Server thisServer)
{
    if (thisServer = (Server)malloc(sizeof(struct Server_t)))
    {
        thisServer->UsersList = CreateLinkedList();
        return Success;
    }
    return Failed;
}

如果要按值返回Server,则必须将指针传递给函数:

Result CreateServer(Server *thisServer)
{
    if (*thisServer = (Server)malloc(sizeof(struct Server_t)))
    {
        (*thisServer)->UsersList = CreateLinkedList();
        return Success;
    }
    return Failed;
}

由于CreateServer() 返回后使用的struct Server_t 值尚未初始化,原始代码会泄漏内存并引发分段错误。


工作代码

以下代码在valgrind 下工作(系统分配的内存仍然可以访问,但没有泄漏或滥用)。如前所述,问题确实出在CreateServer() 函数中。

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

typedef int Element;

typedef struct Node *Node;
struct Node
{
    Node    m_prev;
    Node    m_next;
    Element m_data;
};

struct LinkedList
{
    Node m_head;
    Node m_tail;
    int m_numOfElements;
};

typedef struct LinkedList *List;

struct Server_t
{
    List UsersList;
};
typedef struct Server_t *Server;
typedef enum Result { Failed, Success } Result;

extern Result CreateServer(Server *thisServer);
extern Result AddNode(List list, Element data);
extern void SetPrev(Node node, Node toSet);
extern void SetNext(Node node, Node toSet);
extern Node CreateNewNode(Element data);
extern List CreateLinkedList(void);
extern void DestroyServer(Server server);
extern void DestroyLinkedList(List list);

List CreateLinkedList(void)
{
    List list = (List)malloc(sizeof(struct LinkedList));

    if (list == NULL)
    {
        printf("memory alloc failed\n");
        return NULL;
    }
    list->m_head = NULL;
    list->m_tail = NULL;
    list->m_numOfElements = 0;

    return list;
}

Node CreateNewNode(Element data)
{
    Node newNode = (Node)malloc(sizeof(struct Node));

    newNode->m_next = NULL;
    newNode->m_prev = NULL;
    newNode->m_data = data;
    return newNode;
}

void SetNext(Node node, Node toSet)
{
    node->m_next = toSet;
}

void SetPrev(Node node, Node toSet)
{
    node->m_prev = toSet;
}

Result AddNode(List list, Element data)
{
    Node newNode;
    //there is no linked list to add the element to
    if (list == NULL)
        return Failed;

    newNode = CreateNewNode(data);

    if (newNode == NULL)
    {
        printf("Failed allocating memory\n");
        return Failed;
    }

    //Empty Linked List
    if (list->m_head == NULL)
    {
        list->m_tail = list->m_head = newNode;
    }
    else
    {
        SetNext(list->m_tail,newNode);
        SetPrev(newNode, list->m_tail);
        list->m_tail = newNode;
    }
    //increase num of elements
    list->m_numOfElements++;
    return Success;
}

Result CreateServer(Server *thisServer)
{
    if ((*thisServer = (Server)malloc(sizeof(struct Server_t))) != 0)
    {
        if (((*thisServer)->UsersList = CreateLinkedList()) != 0)
            return Success;
    }
    return Failed;
}

void DestroyLinkedList(List list)
{
    Node node;
    Node next;
    assert(list != 0);
    for (node = list->m_head; node != 0; node = next)
    {
        next = node->m_next;
        free(node);
    }
    free(list);
}

void DestroyServer(Server server)
{
    assert(server != 0);
    assert(server->UsersList != 0);
    DestroyLinkedList(server->UsersList);
    free(server);
}

int main(void)
{
    Server mainFacebookServer;
    if (CreateServer(&mainFacebookServer) == Success)
    {
        if (AddNode(mainFacebookServer->UsersList, 1) == Success)
        {
            /* Use new user list */
        }
        DestroyServer(mainFacebookServer);
    }
    return(0);
}

在 MacOS X 10.7.2 上使用 XCode 4.x GCC/LLVM 编译并使用 Valgrind 3.7.0 运行时,我得到:

$ /usr/bin/gcc -O3 -g -std=c99 -Wall -Wextra -Werror xxx.c -o xxx 
$ valgrind --leak-check=full xxx 
==51464== Memcheck, a memory error detector
==51464== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==51464== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==51464== Command: xxx
==51464== 
==51464== 
==51464== HEAP SUMMARY:
==51464==     in use at exit: 2,095 bytes in 32 blocks
==51464==   total heap usage: 35 allocs, 3 frees, 2,151 bytes allocated
==51464== 
==51464== LEAK SUMMARY:
==51464==    definitely lost: 0 bytes in 0 blocks
==51464==    indirectly lost: 0 bytes in 0 blocks
==51464==      possibly lost: 0 bytes in 0 blocks
==51464==    still reachable: 2,095 bytes in 32 blocks
==51464==         suppressed: 0 bytes in 0 blocks
==51464== Reachable blocks (those to which a pointer was found) are not shown.
==51464== To see them, rerun with: --leak-check=full --show-reachable=yes
==51464== 
==51464== For counts of detected and suppressed errors, rerun with: -v
==51464== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
$

使用--show-reachable=yes 运行时,额外的报告与此类似(如您所见,来自不同的运行:

==51375== 616 bytes in 7 blocks are still reachable in loss record 8 of 8
==51375==    at 0xC3F3: calloc (vg_replace_malloc.c:569)
==51375==    by 0x312AAA: _xpc_calloc (in /usr/lib/system/libxpc.dylib)
==51375==    by 0x313384: _xpc_base_create (in /usr/lib/system/libxpc.dylib)
==51375==    by 0x319CE2: xpc_string_create (in /usr/lib/system/libxpc.dylib)
==51375==    by 0x318EF5: xpc_dictionary_set_string (in /usr/lib/system/libxpc.dylib)
==51375==    by 0x31AF49: _libxpc_initializer (in /usr/lib/system/libxpc.dylib)
==51375==    by 0x18E7D: libSystem_initializer (in /usr/lib/libSystem.B.dylib)
==51375==    by 0x7FFF5FC0FD19: ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==51375==    by 0x7FFF5FC0FA65: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==51375==    by 0x7FFF5FC0D257: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&) (in /usr/lib/dyld)
==51375==    by 0x7FFF5FC0D1F0: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&) (in /usr/lib/dyld)
==51375==    by 0x7FFF5FC0E02A: ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) (in /usr/lib/dyld)
==51375== 

不令人兴奋 - 除了正在进行的大量后台工作 - 并且绝对是系统而不是程序中的代码的问题(或不是)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-14
    • 2015-12-18
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 2017-06-15
    相关资源
    最近更新 更多