刚刚显示的SIGSEGV错误,之前工作正常

时间:2011-12-25 02:40:57

标签: list null sigsegv

我没有解释我的代码发生了什么,我有一个通用的链表 它就像昨天的魅力一样,我没有以任何方式改变它,但不知何故 现在,当列表的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;
}

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

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,然后转到其后的那个,它不应该。什么可以在我的应用程序代码中实现这一点?

编辑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);

结果是枚举,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;
}

1 个答案:

答案 0 :(得分:0)

此代码不符合您的预期:

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;
}

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


工作代码

以下代码在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== 

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