Почему я получаю "дважды без коррупции" со следующим кодом? - PullRequest
0 голосов
/ 29 сентября 2018

Я пишу простую программу, чтобы убедиться, что я полностью понимаю, как работают указатели в Си, когда я прохожу гарвардский CS50.Вот код:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int *a = malloc(sizeof(int));
    *a = 5;
    printf("the address of pointer a is: %p\n", &a);
    printf("the address that a is pointing to is: %p\n", a);
    printf("the contents of a are: %i\n", *a);

    printf("please enter a new value for a: \n");
    scanf("%i", a);
    printf("the address of pointer a is: %p\n", &a);
    printf("the address that a is pointing to is: %p\n", a);
    printf("the contents of a are: %i\n", *a);

    int *b = malloc(sizeof(int));
    *b = 7;
    printf("the address of pointer b is: %p\n", &b);
    printf("the address that b is pointing to is: %p\n", b);
    printf("the contents of b are: %i\n", *b);

    a = b;
    printf("setting a = b\n");
    printf("the address of pointer a is: %p\n", &a);
    printf("the address that a is pointing to is: %p\n", a);
    printf("the contents of a are: %i\n", *a);

    free(a);
    free(b);
}

Компилируется без проблем, но при выполнении я получаю следующую ошибку: "* Ошибка в` ./address ': двойное освобождение или повреждение (fasttop): 0x00000000018b7030 * Прервано "

Эта проблема исчезнет, ​​если я избавлюсь от выражений free (a) или free (b), однако valgrind обнаружит утечку памяти:" == 9626 ==4 байта в 1 блоке определенно теряются в записи потерь 1 из 1 == 9626 == в 0x4C2AB80: malloc (в /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) == 9626 == по 0x4206AD: main (address.c: 6) "

Я просмотрел другие вопросы здесь и другие веб-сайты, которые упоминают двойную свободную коррупцию, но все еще не могу понять, в чем проблема ... У меня есть чувствочто ответ прост, и проблема, вероятно, заключается в утверждении «a = b», однако я не совсем понимаю, почему у меня не было бы возможности иметь один указатель на область памяти, на которую указывает другой,а затем освободить память, занятую обоими указателями ...

Ответы [ 3 ]

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

Когда вы делаете это:

 a = b;

Вы фактически заставляете a и b указывать на один и тот же адрес (он же указатель).Так вот что вызывает ошибку:

free(a); // Frees the location where b points to
free(b);
0 голосов
/ 29 сентября 2018

Давайте сократим ваш код до минимума:

#include <stdlib.h>

int main(void)
{
    int *a = malloc(sizeof(int));
    int *b = malloc(sizeof(int));

    a = b; // after the assignment the pointer value previously held by a is gone.
           // both pointers point to the same memory. The memory previously pointed
           // to by a can no longer be free()d since its address is gone.

    free(a); // free the memory pointed to by b (a is a copy of b) once
    free(b); // free the memory pointed to by b twice --> boom.
}
0 голосов
/ 29 сентября 2018

Вы делаете это:

 a = b; // a now points to the same thing as b does

...

free(a);
free(b);

... что семантически эквивалентно

free(b);
free(b);

Это двойное освобождение - b получает free'd дважды - и этозапрещено в C.


Для вашей проблемы утечки памяти:

Когда вы устанавливаете a = b, вы теряете исходное значение a.a был указателем на память, выделенную вами с помощью int *a = malloc(sizeof(int));, которая теперь потеряна.Вам нужно сохранить этот адрес и передать его free () перед выходом, если вы хотите, чтобы valgrind прекратил жаловаться на утечки.

Для каждого адреса, который возвращает malloc() (кроме нуля ... ^ _ ^)Вы должны позвонить free() с тем же адресом, что и аргумент.

...