Что именно происходит, когда вы передаете указатель значения, который уже выделен? - PullRequest
0 голосов
/ 05 января 2019

Что здесь происходит с точки зрения распределения? Неправильно ли использовать такие указатели?

void f(int p[])
{ 
  p = (int*)malloc(sizeof(int));
  *p = 0;
}

int main()
{
  int *q = 0;
  q = (int*)malloc(sizeof(int));
  *q = 1;
  f(q);
  return 0;
}

Ответы [ 3 ]

0 голосов
/ 05 января 2019

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

И вам нужно помнить, что когда вы отправляете q в функцию, вы отправляете ее по значению так что если вы отметите * q в основном, он все равно останется 1.

если вы хотите изменить значение, на которое указывает q в функции, вы можете отправить f (int **).

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

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

void f(int** p)
{
    free(*p); /*first free the initial main allocated memory on heap */
    *p = malloc(sizeof(int)); /*now the pointer is pointing to the new allocation */
    if(NULL == *p)
    {
       return;
    }
    **p = 0;
}

int main(){
    int *q = NULL;
    q = malloc(sizeof(int)); /*ask for memory allocation */
    if(NULL != q)
    {
       *q = 1;
       f(&q); 
       printf("%d\n", *q); /*now pointer is pointing to the allocationasked for by f */
       free(q); /*free the allocated place on heap */
     }
    return 0;
   }
0 голосов
/ 05 января 2019

Короткий ответ: p и q являются независимыми переменными. Поэтому сначала p будет присвоено то же значение, что и q, а затем p получит новое значение из-за malloc. q не изменяется при вызове функции. Однако имеется утечка памяти из-за того, что pq) не были освобождены.

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

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

void f(int p[]) 
{
    printf("--------------------\n");
    printf("p is now %p\n", (void*)p);
    printf("p points to the value %d\n", p[0]);
    p = (int*)malloc(sizeof(int)); 
    *p = 0; 
    printf("--------------------\n");
    printf("p is now %p\n", (void*)p);
    printf("p points to the value %d\n", p[0]);
    printf("--------------------\n");
}

int main(){
    int *q = 0;
    q = (int*)malloc(sizeof(int));
    *q = 1;
    printf("q is now %p\n", (void*)q);
    printf("q points to the value %d\n", q[0]);
    f(q);
    printf("q is now %p\n", (void*)q);
    printf("q points to the value %d\n", q[0]);
    return 0;
}

Вывод (с несколькими комментариями для объяснения):

q is now 0x1912010        // In main q is initialized
q points to the value 1   // In main the location q points to is initialized
--------------------
p is now 0x1912010        // In function p first has the same value as q
p points to the value 1   // so it also points to the same as q
--------------------
p is now 0x1913040        // In function p gets a new value due to malloc
p points to the value 0   // and the pointed to memory gets a new value
--------------------
q is now 0x1912010        // Back in main q is the same as before the function call
q points to the value 1   // and the pointed to memory is unchanged as well
0 голосов
/ 05 января 2019

Что я угадаю ваш вопрос о том, что это задание

p = malloc(...)

в функции f.

Это полностью допустимое назначение и работает как любое другое назначение.


Рассмотрим этот код:

void f(int p)
{
    p = 0;
}

int main(void)
{
    int q;
    q = 1;
    f(q);
}

В функции f есть переназначение переменной p, как в показанном вами коде. Это действительно так же, как для вашего кода. Не имеет значения, является ли p простой переменной int или указателем. Вы все еще можете переназначить его столько, сколько хотите.

Следует отметить, что аргументы в C передаются по значению . Это означает, что значение аргумента скопировано в переменную аргумента функции (p в вашем случае и в моем примере). Изменение копии (т.е. p), конечно, не приведет к изменению оригинала. Все модификации, которые выполняет функция f, будут потеряны после ее возврата.

Таким образом, в моем примере, если вы напечатаете значение q после вызова f(q), то будет показано, что q равно 1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...