valgrind - Адрес- - это 0 байтов после блока размером 8

19

Во-первых, я знаю, что похожие вопросы задавались. Однако я хотел бы задать более общий простой вопрос с действительно примитивными типами данных C. Так и здесь.

В main.c я вызываю функцию для заполнения этой строки:

int
main (int argc, char *argv[]){

    char *host = NULL ;
    char *database ;
    char *collection_name;
    char *filename = ""; 
    char *fields = NULL;
    char *query = NULL;
    ...

    get_options(argc, argv, &host, &database, &collection_name, &filename, 
                &fields, &query, &aggregation);

Внутри get_options :

if (*filename == NULL ) {
   *filename = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+4);
    strcpy(*filename, *collection_name);
    strcat(*filename, ".tde");  # line 69 
}

Моя программа работает нормально, но потом Valgrind говорит мне, что я делаю это неправильно:

==8608== Memcheck, a memory error detector
==8608== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==8608== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==8608== Command: ./coll2tde -h localhost -d test -c test
==8608== 
==8608== Invalid write of size 1
==8608==    at 0x403BE2: get_options (coll2tde.c:69)
==8608==    by 0x402213: main (coll2tde.c:92)
==8608==  Address 0xa2edd18 is 0 bytes after a block of size 8 alloc'd
==8608==    at 0x4C28BED: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8608==    by 0x4C28D6F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8608==    by 0x403BBC: get_options (coll2tde.c:67)
==8608==    by 0x402213: main (coll2tde.c:92)

Можете ли вы объяснить ошибку Address 0xa2edd18 is 0 bytes after a block of size 8 alloc'd ? Как я могу решить эту проблему?

    
задан Oz123 24.12.2014 в 12:36
источник

1 ответ

31

strcpy добавляет нулевой символ-терминатор '".tde"' . Вы забыли выделить место для него:

*filename = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+5);

Вам нужно добавить пробел для 5 символов: 4 для суффикса 'realloc' и еще один для терминатора realloc . Ваш текущий код выделяет только 4, поэтому последняя запись выполняется в пространство сразу после блока, выделенного для нового имени файла (то есть 0 байт после него).

Примечание. У вашего кода есть общая проблема - он присваивает результаты realloc непосредственно перераспределяемому указателю. Это нормально, когда NULL успешен, но создает утечку памяти при сбое. Исправление этой ошибки требует сохранения результата *filename в отдельной переменной и проверки его на *filename , прежде чем присваивать значение обратно *filename :

char *tmp = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+5);
if (tmp != NULL) {
    *filename = tmp;
} else {
    // Do something about the failed allocation
}

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

    
ответ дан dasblinkenlight 24.12.2014 в 12:39
  • douh! Я пробовал это раньше, и по какой-то причине я удаляю его. Поэтому мне нужно быть более осторожным здесь! Но почему смутный английский? Если моя новая строка больше на 1, почему valgrind говорит: 0 байт после ...? –  Oz123 24.12.2014 в 12:42
  • Хорошо, вы уже видели, как это происходит. Итак, 0 байт после того, как разработчики Valgrind способ сказать мне простым языком: «Это смежно» или «сразу после него». –  Oz123 24.12.2014 в 12:43
  • @ Oz123: 0 байт после того, как это правильно, как 42 байта после, не так ли? –  alk 24.12.2014 в 12:45
  • @ Oz123 Скажем, блок начинается с 0x8000 и имеет длину 8 байтов. Тогда последний действительный адрес блока будет 0x8007, а 0x8008 будет первым недопустимым адресом после него. Когда valgrind видит запись в 0x8008, она сообщает об этом как запись в начальный байт незаконного блока, как если бы он был массивом байтов, и он использует нотацию для уведомления о смещении. –  dasblinkenlight 24.12.2014 в 12:46
  • @ Ac3_DeXt3R «Подобный» не является достаточно конкретным. Задайте новый вопрос и предоставьте все детали. –  dasblinkenlight 13.03.2018 в 15:09