Valgrind неверное чтение / запись при добавлении символа в строку C - PullRequest
0 голосов
/ 21 сентября 2018

Я пытаюсь разобрать строку (размер варьируется от статьи до целой книги) и создать временный связанный список для хранения каждого отдельного слова, разделенного любыми пробельными символами.Я написал свою собственную функцию charAppend(), так как не думаю, что смогу использовать strcat() и передавать char* str и char c в качестве аргументов.В конечном итоге моя цель состоит в том, чтобы организовать этот связанный список слов в хеш-таблицу, и когда я попытался вывести содержимое хеш-таблицы в формате <word>:<number of occurrences> с помощью printf, я получил ошибку сегмента.Аргументы printf на GDB кажутся нормальными, но когда я запустил valgrind, я получил много Invalid write of size 1 и Invalid read of size 1 в моей функции charAppend().Я не понимаю, что здесь происходит, поскольку использование gdb не дало мне много информации.

my charAppend() function:

//str is my current word, and c is the character I'm trying to append 
char* charAppend(char* str, char c) { 
    int length = 0;
    if (str != NULL) {
        length = strlen(str);
        str[length] = c;
        str = realloc(str, length+1);
        str[length+1] = '\0';
    }
    else {
        str = malloc(2); //1 for c, 1 for \0
        str[0] = c;
        str[1] = '\0';
    }
    return str;
}

А вот некоторые сообщения об ошибках:

строка 191 равна str[length+1] = '\0';

% valgrind --leak-check=full --track-origins=yes test_wc wc-small.txt
==21794== Memcheck, a memory error detector
==21794== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==21794== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==21794== Command: test_wc wc-small.txt
==21794== 
==21794== Invalid write of size 1
==21794==    at 0x109528: charAppend (wc.c:191)
==21794==    by 0x108EB5: wc_init (wc.c:47)
==21794==    by 0x108DAB: main (test_wc.c:47)
==21794==  Address 0x54db1e2 is 0 bytes after a block of size 2 alloc'd
==21794==    at 0x4C2DDCF: realloc (vg_replace_malloc.c:785)
==21794==    by 0x109513: charAppend (wc.c:190)
==21794==    by 0x108EB5: wc_init (wc.c:47)
==21794==    by 0x108DAB: main (test_wc.c:47)
==21794== 
==21794== Invalid read of size 1
==21794==    at 0x4C2EDB4: strlen (vg_replace_strmem.c:454)
==21794==    by 0x1094E5: charAppend (wc.c:188)
==21794==    by 0x108EB5: wc_init (wc.c:47)
==21794==    by 0x108DAB: main (test_wc.c:47)
==21794==  Address 0x54db1e2 is 0 bytes after a block of size 2 alloc'd
==21794==    at 0x4C2DDCF: realloc (vg_replace_malloc.c:785)
==21794==    by 0x109513: charAppend (wc.c:190)
==21794==    by 0x108EB5: wc_init (wc.c:47)
==21794==    by 0x108DAB: main (test_wc.c:47)

Есть как минимум еще 10 таких сообщений об ошибках, некоторые Conditional jump or move depends on uninitialised value(s) в результате строки 190, str = realloc(str, length+1); и несколько, которые могут быть следствием этого, когда я пытаюсь напечатать содержимое хеш-таблицы, которое ядаже не понимаю.

==21794== Invalid read of size 8
==21794==    at 0x1092CE: wc_output (wc.c:124)
==21794==    by 0x108DD1: main (test_wc.c:51)
==21794==  Address 0xffefffe20 is on thread 1's stack
==21794==  1680 bytes below stack pointer
==21794== 
==21794== Invalid read of size 8
==21794==    at 0x1092EA: wc_output (wc.c:125)
==21794==    by 0x108DD1: main (test_wc.c:51)
==21794==  Address 0xffefffe20 is on thread 1's stack
==21794==  1680 bytes below stack pointer

Я думаю, что у меня нет правильного понимания того, как работают строки C (особенно их изменение) (Прошло 2 года с тех пор, как я прошел курс C на вводном уровне), но любая помощь в том, что пошло или может быть не так, и предложения о том, как их отладить, будут оценены!

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

1 Ответ

0 голосов
/ 21 сентября 2018

В этой части есть несколько ошибок:

    length = strlen(str);
    str[length] = c;
    str = realloc(str, length+1);
    str[length+1] = '\0';

1) strlen не не дает вам объем выделенной памяти.Это дает сумму минус 1 .Это потому, что strlen не включает завершение строки.Таким образом, ваш realloc неверен.

2) Никогда realloc непосредственно в целевой указатель.realloc может вернуть NULL

Так что попробуйте:

    length = strlen(str);
    char * tmp = realloc(str, length+2); // note +2
    if (tmp == NULL) exit(1);            // bad error
    str = tmp;
    str[length] = c;
    str[length+1] = '\0';
...