0

Bellow is the relevant code:

typedef struct Node_t {
    ListElement data;
    struct Node_t* next;
} Node;

struct List_t {
    Node* head;
    Node* tail;
    Node* current;
    int size;
    CopyListElement copyF;
    FreeListElement freeF;
};

static ListResult initializeNode(List list, ListElement element, Node* newNode){
    printf("\nEntered initializeNode\n");
    if ((list == NULL) || (element == NULL)) return LIST_NULL_ARGUMENT;
    newNode = malloc(sizeof(Node));
    if (newNode == NULL) return LIST_OUT_OF_MEMORY;
    printf("\nWithin initializeNode, before copyF\n");
    ListElement newElement = list->copyF(element);
    printf("\nWithin initializeNode, after copyF\n");
    if (newElement == NULL) return LIST_OUT_OF_MEMORY;
    newNode->data = newElement;
    printf("\nLast line within initializeNode\n");
    return LIST_SUCCESS;
}

List listCreate(CopyListElement copyElement, FreeListElement freeElement){

    //Check if there is a NULL argument.
    if ((copyElement == NULL) || (freeElement == NULL)) return NULL;

    //Check wether there is enough memory.
    List newList = malloc(sizeof(List));
    if (newList == NULL) return NULL;
    //Initialize an empty List.
    newList->head = NULL;
    newList->tail = NULL;
    newList->size = 0;
    newList->current = NULL;
    newList->copyF = copyElement;
    newList->freeF = freeElement;

    return newList;
}

ListResult listInsertFirst(List list, ListElement element){
    printf("\nEntered listInsertFirst\n");
    Node* newNode;
    ListResult result = initializeNode(list, element, newNode);
    printf("\n Node was initialized\n");
    if (result != LIST_SUCCESS) {
        return result;
    }

    printf("\nEntering logistic works within listInsertFirst\n");
    //Finish logistic work within the Node.
    newNode->next = list->head;
    list->head = newNode;
    list->size++;
    printf("\nElement was inserted successfully\n");

printf("\nCheck list->CopyF within listInsertFirst\n");
list->copyF(element);
printf("\nCheck list->CopyF within listInsertFirst: PASSED\n");

    return LIST_SUCCESS;
}

Within main function I'm trying:

List list = listCreate(&copyInt, &freeInt);

ListResult result;
int el=2;
//ListElement e1;
//ListElement e2;

result = listInsertFirst(list,&el);
printf("\nresult = %d\n", result);

result = listInsertFirst(list,&el);
printf("\nresult = %d\n", result);

After compiling and running I get:

Entered listInsertFirst

Entered initializeNode

Within initializeNode, before copyF

Within initializeNode, after copyF

Last line within initializeNode

Node was initialized

Entering logistic works within listInsertFirst

Element was inserted successfully

Check list->CopyF within listInsertFirst Segmentation fault: 11

For some reason the pointer [to function] list->copyF gets corrupted [I think].

1
  • What compiler flags are you using? The first thing I would try is adding -Wall -Wextra. Also, have you tried Valgrind? Commented Apr 29, 2013 at 6:58

2 Answers 2

1

I'm assuming this is C code, not C++, based on the tags. Given that you have a mix of data definitions and actual code statements, which I wouldn't expect to work in C, I'm not 100% sure it is real C, in which case I may be wrong about the error below.

First of all, the interface to initializeNode() doesn't do what you probably intend. You probably want:

static ListResult initializeNode(List list, ListElement element, Node** newNodep)
{
    Node *newNode = malloc(sizeof(Node));
    if (newNode == NULL) return LIST_OUT_OF_MEMORY;
    ListElement newElement = list->copyF(element);
    if (newElement == NULL) return LIST_OUT_OF_MEMORY;
    newNode->data = newElement;
    *newNodep = newNode;
    return LIST_SUCCESS;
}

That way the Node you create gets passed back.

I don't know what CopyInt() does, but if it's really the function hitting the Bus Error the bug with initializeNode() can't be your problem. However, it's possible that you aren't seeing the output of all your printfs before the crash gets reported.

If CopyInt() does what I'd expect, it does something like:

ListElement CopyInt(int *val)
{
    ListElement *e = malloc(sizeof(ListElement));
    if (e) 
        e->val = *val;
    return e;
}

The only way you are going to get a second-time bus error here is if you've messed up the data structures maintained by the library function malloc(). Unfortunately for that theory, I don't see anything worse than a memory leak here.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer, it will take me some time to analyze it. BTW, this is C99.
initializeNode get a pointer to a Node, so i don't think your fix for initializeNode is "good".
0

My guess that the bug that actually causes the crash is this line:

newNode->next = list->head;

Like @Arlie Stephens said - code for initializeNode doesn't do anything as the pointer is passed by value and the actual pointer still points to junk. So when you do newNode->next = list->head; you're basically writing to an unknown address and it's very likely to get a segmentation fault. Why does it only happens on the second call? No idea, it's undefined behavior.

Crazy idea - it's possible that newNode->next is initialized to the address of copyF and trying to write into it cause you to corrupt copyF...Try printing the address of newNode->next and the address of copyF.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.