1

I'm working on a List example in C where new nodes are pushed on to the end of the stack. I keep getting a Bus Error: 10 when I try to push the new node on to the end. Here is my push function:

void push(struct node *tail, struct node *newNode) {

tail->next = newNode; // gdb says the problem is here
tail = tail->next;

}

and I call it using push(tail, newNode);

Also here is my struct if necessary:

struct node
{
    int hour;
    int minute;
    char *name;
    struct node *next;
};

And here is the main function showing code leading to push()

int main()

{
char inputString[50];
int timeHour, timeMin;  
struct node *head;
struct node *tail;

while ((scanf("%d:%d", &timeHour, &timeMin)) != EOF) {
    scanf("%s", inputString);

    if (strcmp(inputString, "enqueue") == 0) {
        if (head == NULL) {
            head = malloc(sizeof(struct node));

            head->hour = timeHour;
            head->minute = timeMin;

            // get name
            scanf("%s", inputString);
            head->name = malloc(strlen(inputString)+1);
            strcpy(head->name, inputString);

            tail = head;

            printEnqueue(head);
        } else {
            struct node *newEntry = malloc(sizeof(struct node));

            newEntry->hour = timeHour;
            newEntry->minute = timeMin;

            // get name
            scanf("%s", inputString);
            newEntry->name = malloc(strlen(inputString)+1);
            strcpy(newEntry->name, inputString);

            push(tail, newEntry);

            printEnqueue(newEntry);
        }
    } else {
        pop(&head, timeHour, timeMin);
    }
}

return 0;
}
Slayter
  • 1,172
  • 1
  • 13
  • 26
  • 1
    Why are you passing a pointer to a pointer to the `newNode` into the function? You aren't modifying the pointer to `newNode`, so you can just pass the pointer in. Also, when you step into it in the debugger, what is *newNode pointing to? Is it a valid node? – user1118321 Apr 16 '13 at 04:02
  • after changing `newNode` to a regular pointer, I got that it was pointing to `newNode=0x100103920` in gdb. I don't know a whole lot about memory so I'm not sure if that is a valid node or not haha. – Slayter Apr 16 '13 at 04:07
  • 2
    Minimal, **compilable** testcase, please. We don't have all of the information required to answer this question without guessing. – autistic Apr 16 '13 at 04:08
  • @Slayter When you look at the memory of `newNode` in the debugger does it look correct? (I can't tell from just a random value here.) Are the hour, minute, and name the values you expect them to be? Where is `newNode` coming from? How is it constructed before you pass it in to your function? – user1118321 Apr 16 '13 at 04:11
  • updated with my `main` function. Let me know if anything else is needed – Slayter Apr 16 '13 at 04:12
  • 1
    @user1118321 I suspect all of those questions would be answered by a minimal, compilable testcase. – autistic Apr 16 '13 at 04:12
  • just checked `newNode` in gdb. It does contain valid values – Slayter Apr 16 '13 at 04:13
  • its a good habit to initialize all your variables. – AndersK Apr 16 '13 at 06:02

3 Answers3

2

I suspect the head and tail node in the main function is not properly initialized.

From your code it seems that head will be allocated a new node if it is NULL. However, your definition of head does not ensure it's initially NULL (neither does tail). So you may bypass the if (head == NULL) branch (make sure they are really executed from gdb please :) ).

The Bus error is rarely seen. So I googled it, and from here, a bus error may occur when

using a processor instruction with an address that does not satisfy its alignment requirements.

This may be because tail is not aligned and code runs directly into else branch. So push(tail, newEntry); will access tail which is not aligned (this also validates my suspect).

Community
  • 1
  • 1
Summer_More_More_Tea
  • 12,740
  • 12
  • 51
  • 83
  • Annnnd that was it! Thanks. – Slayter Apr 16 '13 at 12:55
  • 1
    @Slayter np. So next time, do remember initialise explicitly when defining a varaible. :p – Summer_More_More_Tea Apr 17 '13 at 00:34
  • Yeah I was under the impression that when declaring something like that it defaults to `NULL`. But I guess that's more of an OOP thing? – Slayter Apr 17 '13 at 14:57
  • @Slayter May be if you think the behavior is related to default constructor. But pls be reminded that there is no constructor in c programming language. For `head` and `tail` they are all auto variables, thus is not initialized by default. You can google `auto variable` for details :). – Summer_More_More_Tea Apr 17 '13 at 17:31
1

Amendment #3: while ((scanf("%d:%d", &timeHour, &timeMin)) != EOF) Within the body of this loop, there is no guarantee that the two integers timeHour and timeMin were assigned to. Perhaps you meant while ((scanf("%d:%d", &timeHour, &timeMin)) == 2).


Amendment #2: When you pass a value to a function, you're passing the value, not the variable. The assignment you're making to tail within push isn't visible to the caller (your main). You'll need to pass in a pointer to that variable (eg. &head which is a struct node **) and assign to *tail as you were, previously. Alternatively, you could return newNode; from your push and use the return value as your new head.


Amendment: This doesn't even look like it'll compile. Let's take a look at push.

void push(struct node **tail, struct node *newNode) {
    (*tail)->next = *newNode; // gdb says the problem is here
    *tail = (*tail)->next;
}

What's the type of *newNode? struct node. What's the type of (*tail)->next? That's in this snippet:

struct node
{
    int hour;
    int minute;
    char *name;
    struct node *next;
};

Fix your inconsistency and ensure your minimal, compilable testcase is compilable before you post it.


Don't forget to check the return value of scanf! In your case, it should return 1 unless an error occurs.


        head->name = malloc(strlen(inputString));
        strcpy(head->name, inputString);

This is wrong, because you're not allocating enough space to store a '\0' character. I think you meant malloc(strlen(inputString) + 1). There are two instances of this error in your code. I'm not planning on repeating myself.


        struct node *newEntry = malloc(sizeof(struct node));
        push(&tail, newEntry);

What's the type of newEntry? struct node *.

        void push(struct node **tail, struct node **newNode)

What's the type of newNode? struct node **. Do you see the inconsistency? You need to pass in a struct node **, but newEntry is a struct node *.

autistic
  • 1
  • 3
  • 35
  • 80
  • Sorry I forgot to change my question after I changed `struct node *newNode` to a single pointer. Also after adding the +1 to `strlen(inputString)` it still gives a Bus Error. – Slayter Apr 16 '13 at 04:20
  • @Slayter If you're going to update your question again, make sure you add the malloc fix into it and ensure it compiles. – autistic Apr 16 '13 at 04:27
  • My code has been compiling this whole time just as a side note. I updated the question with the fixes you suggested. However, it appears that `tail` is `NULL` according to gdb so is suspect that may be part of the issue. – Slayter Apr 16 '13 at 04:33
  • Ok, so I compiled the code on my school's UNIX server (was on my Mac mini) and Now I'm getting a segmentation fault in one of my print functions that accesses the struct properly. gdb says that the `name` member is `out of bounds` so I have no clue. But we're getting somewhere. – Slayter Apr 16 '13 at 04:41
  • @Slayter Read my answer very, very carefully and fix the issues one at a time as you read them. Most of the issues I mentioned have gone un-fixed in your update. – autistic Apr 16 '13 at 04:42
  • @Slayter Have you fixed the malloc/strlen issue, yet? Not according to your update. Fix that and the out of bounds issue will go away. Fix the other errors, too. Stop frontin'. – autistic Apr 16 '13 at 04:43
  • Frontin'? haha yeah I fixed the `strlen()` thing and I think I updated with all of your other fixes. My code on my computer gets fixed before I think to update the question. But let me know if you see anything else you think I missed. I'm sorry for "frontin'" lol. – Slayter Apr 16 '13 at 04:46
  • @Slayter `tail->next = *newNode;` probably should be `tail->next = newNode;`, which I addressed previously... I've written another amendment to address another issue that might have popped up. – autistic Apr 16 '13 at 04:54
  • @Slayter My bad. The new amendment didn't get posted. It's been added, now. – autistic Apr 16 '13 at 04:59
  • Alright. well I've banged my head enough tonight. I'll post tomorrow if I figure it out. Thanks. – Slayter Apr 16 '13 at 05:05
1

change

void push(struct node *tail, struct node *newNode) 
{
  tail->next = newNode; // gdb says the problem is here
  tail = tail->next;
}

to

void push(struct node **tail, struct node *newNode) 
{
  (*tail)->next = newNode; // gdb says the problem is here
  (*tail) = (*tail)->next;
}

then call it like this instead

push(&tail, newEntry);

as you have it currently 'tail' will never change since you do not pass the address of the variable to the function so you cannot change what it points to.

also make sure you initialize all your local variables (header,tail,...), make it a habit.

AndersK
  • 35,813
  • 6
  • 60
  • 86
  • That's actually what it originally was but changed it because of someone else's recommendation. This is the way it should be but the real problem was elsewhere. – Slayter Apr 16 '13 at 12:56