C free():在其他函数中分配的指针无效
我是新来的。我现在正在学习C指针 这是我的代码: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
#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语言中,函数参数是“按值传递的”。有两种方法可以解决此问题:
方法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 );