realloc (): неверный следующий размер при перераспределении, чтобы освободить место для strcat на char *

Я получаю недопустимую ошибку памяти в следующем коде:

printf(" %s\n","FINE 5");
printf("%s LENGTH IS: %d\n","FINE 6",strlen(": "));
buffer = (char *)realloc(buffer, strlen(buffer)* sizeof(char) + (strlen(": ")+1)* sizeof(char));
printf(" %s\n","FINE 7");
strcat(buffer, ": \0");

Вывод:

FINE 5
FINE 6 ДЛИНА: 2
* glibc обнаружен * ./auto: realloc(): неверный следующий размер: 0x08cd72e0 *** ======= Backtrace: ========= /lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x6dd591]

Здесь следует отметить, что Fine 7 никогда не печатается. и недопустимая ошибка следующего размера при каждом запуске находится в одном и том же месте.

Найдено этого релевантного


person PUG    schedule 08.12.2011    source источник
comment
Что установлено для buffer перед вызовом realloc?   -  person Brett Hale    schedule 09.12.2011
comment
это указатель, который я все время перераспределяю, у него около 20 символов, которые печатаются правильно   -  person PUG    schedule 09.12.2011
comment
Также вы должны проверить в случае сбоя realloc. Маловероятно, но бывает   -  person Adrian Cornish    schedule 09.12.2011


Ответы (3)


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

Тот факт, что FINE 7 не печатается, говорит о том, что realloc не работает. И этот сбой должен быть вызван тем, что buffer недействителен из-за повреждения кучи в начале выполнения.


Ортогонально вашей реальной проблеме, sizeof(char) по определению является 1, поэтому имеет смысл удалить его из кода.

person David Heffernan    schedule 08.12.2011
comment
@ Дэвид Хеффернан данные в буфере до тех пор, пока Fine 6 не будут напечатаны правильно. - person PUG; 09.12.2011
comment
Если бы не было повреждения кучи, то realloc завершился бы успешно. Буфер может нормально печатать, но повреждены метаданные блока памяти. При выделении памяти также будет блок заголовка, который используется распределителем внутри. Вот что коррумпировано. В любом случае, я уже достаточно раз изложил свою точку зрения. - person David Heffernan; 09.12.2011
comment
я использовал strncpy(arr, arrTemp, strlen(arrtTemp)) я должен был использовать strncpy(arr, arrTemp, strlen(arrtTemp)+1) - person PUG; 09.12.2011

Как указывает Дэвид Хеффернан, ваша корневая проблема должна быть диким указателем в другом месте вашего кода, разбивающим кучу.

Однако в этом фрагменте кода есть еще несколько вещей, о которых стоит подумать:

  1. Нет необходимости в sizeof (char) в новом выражении размера, так как sizeof (char) по определению равен 1.

  2. Никогда не назначайте возврат из realloc непосредственно обратно единственному указателю на буфер, который вы перераспределяете. Если realloc возвращает NULL при ошибке, вы потеряете указатель на старый буфер и получите собственную утечку памяти. Вы всегда хотите сделать соответствующий эквивалент:

    footype *p = realloc(oldbuff, newsize);
    if (!p) {
        handle_error();
    } else {
        oldbuff = p;
    }
    
  3. В C void * будет автоматически преобразован в правильный тип при присваивании, приведение не требуется. Кроме того, при приведении в некоторых случаях вы не получите полезных сообщений об ошибках, если забудете включить объявление рассматриваемой функции.

  4. Строковые литералы включают подразумеваемый нулевой терминатор. Вы хотели сказать:

    strcat(буфер, ": ");

С другой стороны, strcat остановится на первом нулевом символе, так что в этом случае нет никакого вреда.

person Greg Jandl    schedule 08.12.2011
comment
Отсутствие переполнения буфера за счет включения дополнительного \0. strcat перейдет к первому \0. Он никогда не увидит второго. Вы можете поместить туда столько нулевых терминаторов, сколько захотите. - person David Heffernan; 09.12.2011
comment
Ах... конечно, strcat остановится на первом нуле в строке для копирования. Я исправлю свой ответ и отмечу для себя, что отвечать во время работы - плохая идея! - person Greg Jandl; 09.12.2011
comment
@ 4 уже пробовал, ничего не изменилось - person PUG; 09.12.2011
comment
@jaminator Не ведитесь на все эти разговоры о strcat. Проблема где-то еще в вашем коде, где вы испортили кучу. Это не в коде, который вы публикуете здесь. - person David Heffernan; 09.12.2011
comment
Дэвид прав - у вас есть дикий указатель где-то еще, который разбивает вашу кучу. - person Greg Jandl; 09.12.2011

(char *)realloc(buffer, strlen(buffer)* sizeof(char) + (strlen(": ")+1)* sizeof(char));

Должно быть

(char *)realloc(buffer, (strlen(buffer) + strlen(": ") + 1) * sizeof(char));

не должно? Вы ошибаетесь в математике длины строки.

person Grambot    schedule 08.12.2011
comment
Это не так, потому что ac + bc == (a+b)*c - person David Heffernan; 09.12.2011
comment
Эти утверждения эквивалентны. - person Brett Hale; 09.12.2011
comment
В любом случае не имеет значения, потому что char = 1 байт. а * 1 = а - person Jonathon; 09.12.2011