SIGSEGV ошибки, которые только что показали, работали хорошо раньше - PullRequest
0 голосов
/ 25 декабря 2011

У меня нет объяснения того, что происходит с моим кодом, у меня есть общий связанный список и это сработало как вчерашний день, я никак не изменил его, но каким-то образом теперь, когда получатели и установщики списка пытаются добраться до полей списка или его узлов, я получаю эти ошибки 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;
}

У меня также есть этот typedef в файле list.h, который включен в файл ilst.c:

typedef struct LinkedList* List;

после отладки в течение нескольких часов я заметил, что голова и хвост не получают значение NULL при создании списка, у них все еще есть некоторый адрес вместо нулей, это также происходит в узле создания и других случаях использования этого списка, почему? моя куча повреждена? почему он не присваивает этим полям значение NULL ?! в любом случае, плз, помню, это работало хорошо, и я понятия не имею, что изменило это .. спасибо!

редактирование:

это функция AddNode в моем файле node.c:

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, когда список пуст и я добавляю первый элемент он переходит по пустому связанному списку и переходит к следующему, что не следует. что может сделать это в моем коде приложения?

изменить 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);

Результат - enum, а 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 голосов
/ 25 декабря 2011

Этот код не делает то, что вы думаете:

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

При компиляции с XCode 4.x GCC / LLVM на MacOS X 10.7.2 и запуске с Valgrind 3.7.0, Iget:

$ /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== 

Не интересно - кромеза объем выполняемой фоновой работы - и определенно проблема (или нет) с системой, а не с кодом в программе.

...