#c #memory-leaks #valgrind
#c #утечки памяти #valgrind
Вопрос:
typedef struct {
int **a;
int **b;
int **c;
int i;
} test_t;
test_t *create(int i) {
test_t *test = malloc(i * sizeof(test_t));
test->i = i;
test->c = malloc(i * sizeof(int *));
for (int j = 0; j < i; j) {
test->c[j] = malloc(sizeof(int *));
}
test->a = malloc(sizeof(int *));
test->a = amp;(test->c[0]);
test->b = malloc(sizeof(int *));
test->b = amp;(test->c[0]);
return test;
}
void delete(test_t *test) {
free(test->a);
free(test->b);
for (int i = 0; i < test->i; i)
free(test->c[i]);
free(test->c);
free(test);
}
int main() {
test_t *test;
test = create(3);
delete(test);
return 0;
}
Что не так с этим кодом?
Когда я запускаю Valgrind, я получаю 5 ошибок и некоторые утечки памяти.
Я не вижу никакой утечки памяти, а вы?
Я получаю такие ошибки, как:
Invalid free() / delete / delete[] / realloc()
Address 0x4a380e0 is 0 bytes inside a block of size 24 free'd
Block was alloc'd at
Invalid read of size 8
Кто-нибудь может мне помочь с этим, пожалуйста?
PS Код работает нормально, но у него есть утечки памяти, поэтому это не так.
Комментарии:
1. @dxiv Извините, опечатка. Посмотрите на это сейчас.
2. @JohnDoe скопируйте / вставьте только тот код, который вы тестировали.
3. ‘test-> a’ получает malloced, но затем перезаписывается в следующей строке. То же самое с test->b.
4.
test->a = malloc(sizeof(int *)); test->a = amp;(test->c[0]);
Как вы думаете, что это делает? Второе выражение перезаписываетmalloc
результат первого. Это приводит к утечке памяти. И когда вы освободитеtest->a
его, он будет где-то внутриc
. Это именно то, что говорит вам valgrind.5. @kaylum хммм. Итак,
test->a = some-address
перезаписываетtest->a
адрес? Когда я пытаюсьprintf
это сделать, он не перезаписывается. Это странно. Я хотел бы сохранить адрес первого элемента в массиве вtest->a
иtest->b
.
Ответ №1:
Наблюдаю за этим…
test->a = malloc(sizeof(int *));
test->a = amp;(test->c[0]);
test->b = malloc(sizeof(int *));
test->b = amp;(test->c[0]);
Поскольку test->a
и test->b
немедленно переназначаются, mallocs не имеют никакого эффекта, кроме утечки памяти. Вышеизложенное должно быть простым…
test->a = amp;(test->c[0]);
test->b = amp;(test->c[0]);
При этом работает эмпирическое правило, согласно которому количество mallocs должно равняться количеству освобождений. Три mallocs, один в цикле. Три освобождения, одно в цикле.
void delete(test_t *test) {
for (int i = 0; i < test->i; i ) {
free(test->c[i]);
}
free(test->c);
free(test);
test->a = NULL;
test->b = NULL;
}
test->a
и test->b
не должны быть освобождены, поскольку они занимают test->c[0]
память. Нам также нужно избегать освобождения его дважды. Поскольку эта заимствованная память недействительна и больше не может использоваться, мы устанавливаем ее в NULL
качестве меры предосторожности.