Segfault при возврате значения типа int; - PullRequest
1 голос
/ 17 февраля 2012

Я знаю, что этот вопрос может показаться довольно глупым, но я старался изо всех сил, и я не могу решить проблемы с этим кодом:

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;

Он вызывает ошибки при return ingпоскольку printf выполняется нормально, а другой printf вызов / после / вызываемая функция (на int main()) вообще ничего не печатает.

Извините, если этозвучит слишком специфично, но я не знаю, где еще можно получить помощь.

Ответы [ 5 ]

3 голосов
/ 17 февраля 2012

Видимо, вы как-то портите стек.ваша строка не инициализирует указатель:

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

, но вы пишете так, что будет иметь неопределенное поведение:

statms[sta] = statm;

Самый простой способ исправить это, вероятно, восстановить malloc(при условии, что размер правильный)

struct bacon_statement* statms = (struct bacon_statement*)malloc(3000 * sizeof(struct bacon_statement));
2 голосов
/ 17 февраля 2012

Похоже на переполнение стека, вы продолжаете назначать данные в буфер (statms) без проверки границ. Рано или поздно, адрес возврата (который находится в стеке) будет переопределен, и когда возврат будет достигнут, адрес для возврата будет поврежден. и есть ваша ошибка сегментации.

1 голос
/ 17 февраля 2012

Код делает слишком много. Позвольте мне подвести итог:

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;

Но мы можем стать более компактными:

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;

Теперь давайте удалим глупую строку:

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;

Все еще не имеет смысла. IMO ОП хочет зациклить массив строк-указателей (yay) и обработать каждую строку в нем. Особенно *(yay)++ выглядит неловко.

Может быть, с "#" он хочет пропустить комментарии. Я ожидаю что-то вроде:

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

Если подумать, я предполагаю, что функция strsplit () возвращает указатель на автоматическую ("стек") переменную. Или переменная * yay увеличивается до неузнаваемости. Или массив statms [] индексируется вне границ.

1 голос
/ 17 февраля 2012

Попробуйте сделать что-то вроде:

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

для прогнозирования количества утверждений, а затем:

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

, чтобы выделить достаточно bacon_statement слотов. Альтернативы, вероятно, более сложны: связанный список или другая изменяемая структура; или используя realloc для увеличения размера массива, сохраняя при этом количество оставшихся соц.

Ошибка все еще может быть в других функциях!

0 голосов
/ 17 февраля 2012

Возможно ли, что вы хотели использовать ind вместо sta в качестве переменной индекса массива и sta неинициализирован?

...