Matoe
Matoe

Reputation: 2758

Segfault when returning an int value;

I know this question might sound quite stupid, but I've tried my best and I can't seem to have solved issues with this code:

struct bacon_statement* statms;// = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));

int ind = 0;
char** yay = strsplit(code, ";");
char* a = *yay;

while (a != NULL) {

    puts(a);

    if (strncmp(a, "#", 1)) {
        struct bacon_statement statm;
        int valid = bacon_make_statement(a, statm);
        if (valid != 0) { return valid; }

        statms[sta] = statm;
    }

    sta++;
    *(yay)++;
    a = *yay;
}

puts("Running BACON INTERNAL MAKE");
int ret = bacon_internal_make(statms, internal);
printf("%d\n", ret);
return ret;

It segfaults when returning, since it the printf is executed alright., and another printf call /after/ the function is called (on int main()) doesn't print anything at all.

I'm sorry if this sounds too specific, but I don't know where else to get help.

Upvotes: 1

Views: 1611

Answers (5)

wildplasser
wildplasser

Reputation: 44250

The code does too much. Let me summarise:

struct bacon_statement* statms;// = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));

int ind = 0;
char** yay = strsplit(code, ";");
char* a;

while ((a = *yay)) {

    puts(a);

    if (strncmp(a, "#", 1)) {
        struct bacon_statement statm;
        int valid = bacon_make_statement(a, statm);
        if (valid != 0) { return valid; }

        statms[sta] = statm;
    }

    sta++;
    *(yay)++;
}

puts("Running BACON INTERNAL MAKE");
int ret = bacon_internal_make(statms, internal);
printf("%d\n", ret);
return ret;

But we can get more compact than that:

struct bacon_statement* statms;// = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));

int ind = 0;
char** yay;;
char* a;

for (yay = strsplit(code, ";"); (a = *yay); *(yay)++ ) {

    puts(a);

    if (strncmp(a, "#", 1)) {
        struct bacon_statement statm;
        int valid = bacon_make_statement(a, statm);
        if (valid != 0) { return valid; }

        statms[sta] = statm;
    }

    sta++;
}

puts("Running BACON INTERNAL MAKE");
int ret = bacon_internal_make(statms, internal);
printf("%d\n", ret);
return ret;

Now let's remove the silly stringcompare:

struct bacon_statement* statms;// = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));

int ind = 0;
char** yay;
char* a;

for (yay = strsplit(code, ";"); (a = *yay); *(yay)++ ) {

    puts(a);

    if (*a != '#') {
        struct bacon_statement statm;
        int valid = bacon_make_statement(a, statm);
        if (valid != 0) { return valid; }

        statms[sta] = statm;
    }

    sta++;
}

puts("Running BACON INTERNAL MAKE");
int ret = bacon_internal_make(statms, internal);
printf("%d\n", ret);
return ret;

Still does not make sense. IMO the OP wants to loop trough an array of string-pointers (yay) and process each string in it. Especially the *(yay)++ looks awkward.

Maybe with the '#' he wants to skip comments. I'd expect something like:

sta=0;
for (yay = strsplit(code, ";"); (a = *yay); yay++ ) {
    int err;
    if (*a == '#') continue;
    /* make bacon from a */
    err = bacon_make_statements(a, statms[sta] );
    if (err) return err;
    sta++; /* could overflow ... */
    }

 /* you need the number of assigned struct members ("sta") to this function */
 return bacon_internal_make(statms,sta internal);

On second thought, my guess is that the strsplit() function return a pointer to an automatic ("stack") variable. Or the *yay variable is incremented beyond recognition. Or the statms[] array is indexed out of bounds.

Upvotes: 1

Jim Rhodes
Jim Rhodes

Reputation: 5095

Is it possible that you meant to use ind instead of sta as the array index variable and sta is uninitialized?

Upvotes: 0

Irfy
Irfy

Reputation: 9597

Try doing something like:

int count = 0;
char *ptr = strchr(code, ';');
while (ptr) {
    count++;
    ptr = strchr(ptr + 1, ';');
}

to predict the number of statements, and then:

struct bacon_statement* statms = (struct bacon_statement*) malloc(
    count * sizeof(struct bacon_statement));

to allocate enough bacon_statement slots. Alternatives are probably more difficult: a linked list or other mutable structure; or using realloc to increase the size of the array, keeping a note of how many sots you have left.

The mistake can still be in the other functions though!

Upvotes: 1

Michael Chinen
Michael Chinen

Reputation: 18717

Apparently you are corrupting the stack somehow. your line does not initialize the pointer:

struct bacon_statement* statms;// = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));

but you write to it like this, which will have undefined behavior:

statms[sta] = statm;

Easiest way to fix is probably to restore the malloc (provided the size is correct)

struct bacon_statement* statms = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));

Upvotes: 3

MByD
MByD

Reputation: 137402

Seems like a stack overrun, you keep assigning data to the buffer (statms) without checking for boundaries. Sooner or later, the return address (which is on the stack) will be overridden and when return is reached, the address to return to will be corrupted. and there is your segmentation fault.

Upvotes: 2

Related Questions