Ошибка valgrind с strcpy: неверное чтение размера 1 - PullRequest
1 голос
/ 04 мая 2020

Я получаю следующую ошибку:

Invalid read of size 1 at 0x4008F4: isNameValid (elections.c:76)

и, похоже, ошибка вызвана функцией strcpy. все же я не знаю, почему это неправильно, так как мой код не будет работать правильно без него. Так как я могу решить эту проблему?

минимальный пример

bool isNameValid(const char *tribe_name) {
    char *str = malloc(sizeof (strlen(tribe_name) + 1));
    if (!str) {
        return false;
    }
    if (!strcpy(str, tribe_name)) {
        free(str);
        return false;
    }
}

PS: он отлично работает, когда tribe_name содержит менее 7 символов, но когда я ввожу больше 7, я получаю ошибка выше.

Ответы [ 2 ]

2 голосов
/ 04 мая 2020
char* str = malloc(sizeof (strlen(tribe_name) + 1));

sizeof (strlen(tribe_name) + 1), по-видимому, оценивается в sizeof(size_t) в вашем случае, потому что sizeof возвращает размер в байтах представления объекта типа выражения, а sizeof(size_t) в современных 64-битных системах с 8 байт больше sizeof(int) с 4 байтами.

Поскольку тип возвращаемого значения strlen имеет тип size_t, а 1 - int, и по правилу большинства значение int будет преобразовано в size_t (больший тип) перед вычислением выражения, если sizeof(size_t) больше sizeof(int), результат (strlen(tribe_name) + 1) будет иметь тип size_t.

Таким образом, память размером size_t объекта с 8 при этом вызове для байта выделяется malloc().

В 8 байтах вы можете хранить только строку из 7 символов плюс требуемый завершающий строку нулевой символ.

Если вы пытаетесь сохранить Строка из более чем 7 символов в этой памяти, вы будете писать за пределами выделенной памяти, что неправильно.


Вместо этого должно быть

char* str = malloc(sizeof(char) * (strlen(tribe_name) + 1));
0 голосов
/ 05 мая 2020

Вы можете сохранить все, что вам нужно, чтобы убедиться, что вы получите правильную длину массива символов, просто используя strdup. Не усложняйте вопросы без необходимости!

Ваш код может быть просто

bool isNameValid(const char *tribe_name) {
    char *str = strdup(tribe_name);
    if (!str) {
        return false;
    }
}
...