Seg ошибка на strcat

Итак, я получаю ошибку seg в своем коде, и я просто не могу понять, что ее вызывает. Кто-нибудь смог поймать то, чего не было у меня?

Логически я пытаюсь создать массив символов (строку), объединяя элементы в конец, а затем добавляя их в массив строк.

то, что в конечном итоге должно выглядеть так: «слово1, слово2, слово3, слово4, слово5... и т. д.»

Ошибка сегмента происходит strcat(str, ", ");

void save_ladder(graphNode *curNode) {

    char *str = malloc(1000 * sizeof(char));

    strcpy(str, "");
    strcat(str, curNode->word);
    strcat(str, ", ");

    graphNode *prev = curNode->prevWord;
    while (prev != NULL) {
            if (prev->prevWord != NULL) {
                strcat(str, prev->word);
                strcat(str, ", "); // SEG FAULT HAPPENS HERE
            }
            else 
                strcat(str, prev->word);

            prev = prev->prevWord;
    }

    ladders[numLadders++] = str;
}

трассировка стека gdb:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004013d1 in save_ladder (curNode=0x6420f0) at wordladder.c:150
150             strcat(str, ", ");

Кто-нибудь знает, почему это может происходить?


person Michael    schedule 09.12.2012    source источник
comment
sizeof(char) всегда равно 1. И покажите еще код, касающийся структур и выделения памяти их содержимому - проблема, вероятно, кроется в них.   -  person ljedrz    schedule 09.12.2012
comment
как это может быть проблемой структуры, если код ошибается в строке strcat? 'strcat(ул, , );' не имеет ничего общего ни с одной из моих структур. Кроме того, он работал в прошлом, а затем внезапно перестал работать.   -  person Michael    schedule 09.12.2012
comment
Вы уверены, что не использовали более 1000 символов, которые вы выделили? Может быть полезно напечатать, как выглядит строка непосредственно перед сбоем.   -  person gil_bz    schedule 09.12.2012
comment
Скорее всего это переполнение буфера. Ожидаете ли вы, что окончательная строка будет содержать 999 символов? Если это так, ошибка должна заключаться в том, что вы добавляете больше символов, чем это, и это определяется вашим связанным списком. Отсюда и структуры.   -  person Thomas Padron-McCarthy    schedule 09.12.2012
comment
Используйте отладчик. Посмотрите на свои переменные. Мы не можем.   -  person n. 1.8e9-where's-my-share m.    schedule 09.12.2012
comment
Я бы начал отладку этой проблемы, поставив точку останова в строке malloc и записав это значение. Затем проверьте, не изменилось ли значение str при возникновении ошибки. Также проверьте, если длина полученной строки меньше 1000 символов.   -  person Rudi    schedule 09.12.2012


Ответы (3)


Возможно переполнение буфера. Поместите следующий код прямо в цикл while и проверьте, так ли это:

printf ("%d %d\n", strlen (str), strlen (prev->word));

Если сумма этих двух чисел приближается к 1000, ваш буфер, вероятно, должен быть больше.

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

Кроме того, есть еще два момента. Во-первых, вам никогда не нужно умножать на sizeof(char), так как это всегда 1 (вы также должны проверить возвращаемое значение malloc на случай, если оно не удастся).

Во-вторых, вы можете упростить построение строки таким образом, без оператора if внутри while:

strcpy(str, curNode->word);
graphNode *prev = curNode->prevWord;
while (prev != NULL) {
    strcat (str, ", ");
    strcat(str, prev->word);
    prev = prev->prevWord;
}
person paxdiablo    schedule 09.12.2012
comment
Да, похоже, это было переполнение буфера. На самом деле строка никогда не должна была быть такой длинной, но каким-то образом я удалил «- 1» где-то еще в своем коде, из-за чего это произошло. Мне потребовалось некоторое время, чтобы найти недостающий - 1, но когда я это сделал, проблема была решена! И спасибо за конструкцию строки. Я работал над этим проектом 12 часов подряд, так что я был в режиме автопилота и ничего не оптимизировал... - person Michael; 09.12.2012

У меня есть 2 вещи, чтобы заметить/замечать/ответить:

  1. Вы используете алгоритм Schlemiel the Painter: на каждом strcat() строка, собранная до сейчас снова пройдено. Вам следует рассмотреть возможность использования указателя курсора, который указывает, где вы сейчас находитесь: замените каждый strcat(str, ...) на strcpy(crsr, ...), за которым следует crsr += strlen(crsr), чтобы установить его в конец строки до сих пор. crsr должно быть установлено на str в начале.

  2. Как писали другие, ваш код подходит только для использования до 1000 символов. Либо ваш structor сломан, либо одна из строк слишком длинная. В любом случае, ваш алгоритм слишком негибкий. Вы должны рассмотреть возможность проверки каждой длины строки перед добавлением, и если она не подходит, realloc() ваш str соответствующим образом. (Не забудьте тогда также обновить crsr.) В этом случае у вас больше нет ограничений.

    Измените размер str в конце на strlen(str) + 1, чтобы не тратить память.

person glglgl    schedule 09.12.2012
comment
Я понял, что просматривал массив символов каждый раз, когда хотел что-то добавить, но не знал, как это обойти, так как я все еще относительно новичок в C. Спасибо! - person Michael; 09.12.2012

Я согласен с ответами о переполнении буфера. Я также согласен с очисткой кода. Однако я думаю, что, возможно, вам следует изучить asprintf или snprintf. В asprintf вы указываете символ **, и он возвращает местоположение новой строки. Это очень полезно, если вам не нужно тщательно управлять памятью самостоятельно. Эта подпрограмма также является расширением GNU, так что имейте в виду. Snprintf позволяет вам передать char * и длину оставшегося буфера, чтобы определить, подойдет ли остальная часть форматирования. Это поймает переполнение.

Вот пример использования asprintf:

char *output = NULL;
char *last = NULL;

prev = curNode;
while (prev != NULL) {
    last = output;
    if (asprintf(&output, "%s,", prev->word) < 0) {
        break;  // error
    }
    if (last != NULL)
        free(last);
    }
    prev = prev->prevWord;
}

// remove trailing ',' here

Примечание: приведенный выше код не тестировался (я пишу это на планшете).

person No One in Particular    schedule 09.12.2012