Подтвердить что ты не робот

Что произойдет, если я дважды использую malloc на одном и том же указателе (C)?

Скажем, например, я создал указатель newPtr, и я использую malloc (некоторый размер), а затем я снова использую malloc (некоторый размер) с тем же указателем. Что происходит? Итак, я создаю второй блок памяти того же размера, что и первый? Указывает ли newPtr на тот же адрес?

Пример:

int *newPtr;
newPtr = malloc(10 * sizeof(int));
newPtr = malloc(10 * sizeof(int));
4b9b3361

Ответ 1

У вашей программы будет утечка памяти. Первое значение newPtr будет потеряно, и вы не сможете free его.

Затем я создаю второй блок памяти того же размера, что и первый?

Да. Вы выделяете второй объект, отличный от первого.

Указывает ли newPtr на тот же адрес?

Нет. Объекты различны, поэтому их адрес отличается.

Ответ 2

Фактически вы не используете malloc на том же указателе. Вы не указываете указатель на malloc вообще. malloc всегда выделяет новую память. Итак, происходит то же самое, что и в случае с любым присваиванием переменной:

int a;
a = 14;
a = 20;

Что происходит с 14? Вы не можете получить к нему доступ больше. В терминах malloc это означает, что у вас больше нет ссылки на возвращаемый указатель, поэтому у вас будет утечка памяти.

Если вы действительно хотите использовать "malloc с тем же указателем", вас может заинтересовать функция realloc:

int *newPtr;
newPtr = malloc(10 * sizeof(int));
newPtr = realloc(newPtr, 10 * sizeof(int)); //*might leak memory*

Из этой ссылки: realloc "изменяет размер блока памяти, на который указывает ptr. Функция может переместить блок памяти в новое место (адрес которого возвращается функцией).


EDIT: Обратите внимание, что если realloc не работает в приведенном выше примере, он возвращает NULL, но память, на которую указывает newPtr, не освобождается. Основываясь на этом ответе, вы можете сделать это:

void *emalloc(size_t amt){
    void *v = malloc(amt);  
    if(!v) {
        fprintf(stderr, "out of mem\n");
        exit(EXIT_FAILURE);
    }
    return v;
}
void *erealloc(void *oldPtr, size_t amt){
    void *v = realloc(oldPtr, amt);  
    if(!v) {
        fprintf(stderr, "out of mem\n");
        exit(EXIT_FAILURE);
    }
    return v;
}

а затем:

int *newPtr;
newPtr = emalloc(10 * sizeof(int));
newPtr = erealloc(newPtr, 10 * sizeof(int));

Ответ 3

Эти инструкции не используют malloc на newPtr.

Заявление newPtr = malloc(10 * sizeof(int)); вызывает следующие операции:

  • sizeof(int).
  • Это значение умножается на 10.
  • malloc вызывается и этот продукт передается ему.
  • malloc возвращает значение.
  • Это значение присваивается newPtr.

Итак, вы видите, что на шаге 3 newPtr никак не участвует. Только после malloc выполняется newPtr.

Когда вы вызываете malloc второй раз, у него нет способа узнать, что вы делаете что-либо с newPtr. Он просто выделяет новое пространство и возвращает указатель на него. Затем этому новому указателю присваивается newPtr, который удаляет старое значение, которое было в newPtr.

В этот момент у вас нет способа узнать, что такое старое значение. Пространство по-прежнему выделено, потому что оно не было освобождено, но у вас нет указателя на него.

Ответ 4

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

Второе назначение, как и при любом назначении, заменит ранее сохраненное значение.

Это означает, что, если вы не сохранили его в другом месте, у вас больше нет указателя на первый выделенный фрагмент памяти. Это утечка памяти.

Кроме того, вы всегда должны проверять, является ли результат, возвращаемый malloc нулевым указателем, и если да, предпримите некоторые корректирующие действия. В простейшем случае это может быть просто печать сообщения об ошибке и завершение программы. Вы определенно не должны предполагать, что вызов malloc преуспел, а затем попытайтесь использовать (несуществующую) выделенную память. (Это не относится к вашему вопросу, но это то, что легко пропустило, тем более, что в большинстве контекстов неудачи распределения встречаются редко.)