C free():在其他函数中分配的指针无效

C free():在其他函数中分配的指针无效,c,C,我是新来的。我现在正在学习C指针 这是我的代码: #include <stdio.h> #include <stdlib.h> int alloc(int* p){ p = (int*) malloc (sizeof(int)); if(!p){ puts("fail\n"); return 0; } *p = 4; printf("%d\n",*p); return 1; } int m

我是新来的。我现在正在学习C指针

这是我的代码:

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

int alloc(int* p){
    p = (int*) malloc (sizeof(int));
    if(!p){
        puts("fail\n");
        return 0;
    }
    *p = 4;
    printf("%d\n",*p);
    return 1;
}

int main(){

    int* pointer;

    if(!alloc(pointer)){
        return -1;
    }else{

        printf("%d\n",*pointer);
    }

    free(pointer);

    return 0;
}
#包括
#包括
int alloc(int*p){
p=(int*)malloc(sizeof(int));
如果(!p){
出售(“失败”);
返回0;
}
*p=4;
printf(“%d\n”,*p);
返回1;
}
int main(){
int*指针;
如果(!alloc(指针)){
返回-1;
}否则{
printf(“%d\n”,*指针);
}
自由(指针);
返回0;
}
我使用:gcc-omain.c编译

错误:free():无效指针:0xb77ac000***


我的代码怎么了?

C中的参数总是通过值传递。因此,当您调用
alloc(pointer)
时,您只需传入
pointer
包含的任何垃圾值。在函数内部,赋值
p=(int*)…
仅修改局部变量/参数
p
。相反,您需要将
指针的地址
传递到
alloc
,如下所示:

int alloc(int **p) {
    *p = malloc(sizeof(int)); // side note - notice the lack of a cast
    ...
    **p = 4; // <---- notice the double indirection here
    printf("%d\n", **p); // <---- same here
    return 1;
}

然后,代码就可以工作了。

C中的所有内容都是按值传递的。这意味着函数总是在传递给函数的内容的本地副本上运行。通常,指针是模拟按引用传递方案的好方法,因为指针和该指针的副本都包含相同的内存地址。换句话说,指针及其副本都指向同一个空间

在您的代码中,问题在于函数alloc获取您传入的指针的本地副本。所以当你做
p=(int*)malloc(sizeof(int))
您正在将
p
的值更改为新的内存地址,但
main
pointer
的值保持不变


您可以通过将指针传递给一个指针,或者通过返回
p
的新值来绕过此问题,您正在将指针逐值传递到
alloc
函数中。尽管该函数接受指向int的指针,但该函数不能修改指针本身。如果您使
alloc
接受
**p
,设置
*p=…
,并从main中传入
&指针
,它应该可以工作

#include <stdio.h>
#include <stdlib.h>
int alloc(int** p){
  *p = (int*) malloc (sizeof(int)); 
  if(!*p){
    puts("fail\n"); 
    return 0; 
  } 
  **p = 4; 
  printf("%d\n",**p);
  return 1; 
} 
int main() { 
  int* pointer; 
  if(!alloc(&pointer)){ 
    return -1;
  } else { 
    printf("%d\n",*pointer);
  } 
  free(pointer);
  return 0;
}
#包括
#包括
内部分配(内部**p){
*p=(int*)malloc(sizeof(int));
如果(!*p){
出售(“失败”);
返回0;
} 
**p=4;
printf(“%d\n”,**p);
返回1;
} 
int main(){
int*指针;
如果(!alloc(&指针)){
返回-1;
}否则{
printf(“%d\n”,*指针);
} 
自由(指针);
返回0;
}

您的代码中有两个主要问题

首先,
alloc
函数通过
malloc
创建指针,但从不释放指针,也不返回指向调用函数的指针。这保证了指针地址的内存永远不会通过
free
命令释放,并且现在存在内存泄漏

其次,
main
中的变量
int*pointer
,没有像您想象的那样被修改。在C语言中,函数参数是“按值传递的”。有两种方法可以解决此问题:

  • 传递一个指向要修改的变量的指针(在本例中,是指向int的指针)
  • 让函数返回指向调用它的函数的指针
  • 以下是我的建议的两个实现:

    方法1


    方法2



    如果希望函数写入类型为
    T
    的非数组参数,则必须传递指向该参数的指针

    void func( T *ptr )
    {
      *ptr = new_value;
    }
    
    void foo ( void )
    {
      T var;
      func( &var ); // writes new value to var
    }
    
    如果
    T
    是指针类型
    Q*
    ,它将如下所示

    void func( Q **ptr )
    {
      *ptr = new_pointer_value;
    }
    
    void foo ( void )
    {
      Q *var;
      func( &var ); // writes new pointer value to var
    }
    
    如果
    Q
    是指针类型
    R*
    ,您将得到

    void func( R ***ptr )
    {
      *ptr = new_pointer_to_pointer_value;
    }
    
    void foo ( void )
    {
      R **var;
      func( &var ); // writes new pointer to pointer value to var
    }
    
    这三种情况的模式都是相同的;您正在传递变量
    var
    的地址,因此形式参数
    ptr
    必须比实际参数
    var
    多一级间接寻址

    一个三段论的nit:代替写作

    p = (int *) malloc( sizeof (int) );
    
    使用

    相反

    在C语言中(从1989年的标准开始),您不需要强制转换malloc的结果<代码>空> /COD>指针可以被分配给其他指针类型,反之亦然,不需要一个强制转换(这在C++中是不正确的,但是如果你正在编写C++,你应该使用<代码>新< /Calp>运算符,而不是<代码> MaloC < /代码>。此外,在1989年版本的语言中,如果您忘记包含
    stdlib.h
    或者在范围中没有
    malloc
    的声明,那么使用cast将掩盖一个bug。不过,自1999年版以来,这并不是一个问题,所以现在它更多的是可读性问题

    表达式
    *p
    的类型是
    int
    ,因此
    sizeof*p
    的结果与
    sizeof(int)
    的结果相同。这样,如果更改
    p
    的类型,就不必修改
    malloc
    调用

    要分配一个值数组,可以使用

    T *p = malloc( sizeof *p * NUM_ELEMENTS );
    
    或者,如果您希望最初将所有内容归零,请使用

    T *p = calloc( sizeof *p, NUM_ELEMENTS );
    

    您永远不会更改
    指针
    ,而且.malloc(sizeof(int))也可以工作。为什么malloc(sizeof(int*)?@Drew:
    sizeof**p
    会更好。
    void func( Q **ptr )
    {
      *ptr = new_pointer_value;
    }
    
    void foo ( void )
    {
      Q *var;
      func( &var ); // writes new pointer value to var
    }
    
    void func( R ***ptr )
    {
      *ptr = new_pointer_to_pointer_value;
    }
    
    void foo ( void )
    {
      R **var;
      func( &var ); // writes new pointer to pointer value to var
    }
    
    p = (int *) malloc( sizeof (int) );
    
    p = malloc( sizeof *p );
    
    T *p = malloc( sizeof *p * NUM_ELEMENTS );
    
    T *p = calloc( sizeof *p, NUM_ELEMENTS );