使用 malloc 时两个变量的内存发生冲突
Memory of two variables are colliding when used malloc
我正在尝试使用 malloc 学习 C 中的内存分配,并在函数内部使用 realloc 增加分配数组的大小。我遇到了这个。当我使用单个变量时,代码运行良好。但是当我为第二个变量分配内存时,它给了我奇怪的输出。
代码如下:
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
# define N 3
void padd(int *a){
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
}
int main()
{
int *d;
int *pA;
int size = N*sizeof(int);
pA = (void *)malloc(size);
//d = (int *)malloc(size);
padd(pA);
printf("outside func= %d",pA[0]);
}
它给我输出:
inside func= 10
outside func= 10
但是如果我取消注释 //d = (int *)malloc(size);行,它给了我
inside func= 10
outside func= -1368048824
作为输出。
这里可能有什么问题?
您应该从 padd
:
获取新指针
int * padd(int * a){
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
return a;
}
//...
int main()
{
//...
pA = padd(pA);
//...
}
或者传递一个指针给指针:
void padd(int **pA){
int *a = *pA;
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
*pA = a;
}
//...
int main()
{
//...
padd(&pA);
//...
}
你的两个程序都有未定义的行为。
函数参数a
void padd(int *a)
是函数的局部变量,由指针pA
的值初始化,在函数调用中用作函数参数
padd(pA);
你可以想象函数定义和它的调用方式如下
padd(pA);
//...
void padd( /* int *a */ ){
int *a = pA;
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
}
因此可以看出,在函数 padd
中更改局部变量 a
不会影响指针 pA
中存储的值,因为函数处理的是指针的值 pA
.
要在函数中更改原始指针 pA
,您需要通过引用将其传递给函数。
在 C 中,按引用传递意味着通过指向对象的指针间接传递对象。因此取消引用指针,您将可以直接访问该对象。
该函数应按以下方式声明和定义
int padd( int **a ){
int sizes = 10*sizeof(int);
int *tmp = realloc( *a, size );
int success = tmp != NULL;
if ( success )
{
*a = tmp;
( *a )[0] = 10;
// or **a = 10;
printf("inside func= %d \n", ( *a )[0] );
}
return success;
}
而且函数可以这样调用
if ( padd( &pA () ) printf("outside func= %d",pA[0]);
注意调用realloc
你应该使用一个中间变量,因为通常函数可以return一个空指针。所以用空指针重新分配原始指针会导致指针的原始值丢失。
另外,当不再需要时,您应该释放所有动态分配的内存
free( pA );
如果realloc
不能扩展缓冲区,它将分配一个新缓冲区,将旧缓冲区的内容复制到它,释放旧缓冲区,并return地址新缓冲区的(或者 NULL
如果它不能满足请求);因此,a
的值可以在 padd
中改变。但是,该更改仅适用于形式参数 a
- 实际参数 pA
不受影响。
根据行为,它 看起来 如果您分配 d
,它会在 pA
之后立即分配,这样 pA
可以' 就地扩展,因此 realloc
正在创建一个新缓冲区并释放旧缓冲区,并且旧缓冲区在 main
.printf
语句之前被覆盖。
您需要编写 padd
,这样对 a
的任何更改都会反映在 pA
中 - return [=] 的(可能是新的)值14=] 或将指针传递给 pA
:
void padd( int **a )
{
size_t sizes = 10 * sizeof (int); // see note 1
int *tmp = realloc( *a, sizes ); // see note 2
if ( tmp )
{
*a = tmp;
(*a)[0] = 10;
printf( "Inside func, (*a)[0] = %d\n", (*a)[0] );
}
else
{
printf ( "Inside func, realloc failed!\n" );
}
}
你会称它为
padd( &pA );
注 1:sizeof
的类型为 size_t
,而不是 int
。
注2:由于realloc
可能returnNULL
,总是将结果赋给一个临时值,并在赋值前检查它回到原来的变量,否则你 运行 失去对你已经分配的内存的访问的风险。此外,强制转换为 void *
是不必要的且令人困惑,因为您将结果分配给 int *
变量。除非您将此代码编译为 C++ 或在 ancient K&R C 编译器下,否则请完全关闭强制转换 - 否则,您的强制转换必须与您正在分配的事物的类型相匹配至,在本例中为 int *
.
我正在尝试使用 malloc 学习 C 中的内存分配,并在函数内部使用 realloc 增加分配数组的大小。我遇到了这个。当我使用单个变量时,代码运行良好。但是当我为第二个变量分配内存时,它给了我奇怪的输出。
代码如下:
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
# define N 3
void padd(int *a){
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
}
int main()
{
int *d;
int *pA;
int size = N*sizeof(int);
pA = (void *)malloc(size);
//d = (int *)malloc(size);
padd(pA);
printf("outside func= %d",pA[0]);
}
它给我输出:
inside func= 10
outside func= 10
但是如果我取消注释 //d = (int *)malloc(size);行,它给了我
inside func= 10
outside func= -1368048824
作为输出。
这里可能有什么问题?
您应该从 padd
:
int * padd(int * a){
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
return a;
}
//...
int main()
{
//...
pA = padd(pA);
//...
}
或者传递一个指针给指针:
void padd(int **pA){
int *a = *pA;
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
*pA = a;
}
//...
int main()
{
//...
padd(&pA);
//...
}
你的两个程序都有未定义的行为。
函数参数a
void padd(int *a)
是函数的局部变量,由指针pA
的值初始化,在函数调用中用作函数参数
padd(pA);
你可以想象函数定义和它的调用方式如下
padd(pA);
//...
void padd( /* int *a */ ){
int *a = pA;
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
}
因此可以看出,在函数 padd
中更改局部变量 a
不会影响指针 pA
中存储的值,因为函数处理的是指针的值 pA
.
要在函数中更改原始指针 pA
,您需要通过引用将其传递给函数。
在 C 中,按引用传递意味着通过指向对象的指针间接传递对象。因此取消引用指针,您将可以直接访问该对象。
该函数应按以下方式声明和定义
int padd( int **a ){
int sizes = 10*sizeof(int);
int *tmp = realloc( *a, size );
int success = tmp != NULL;
if ( success )
{
*a = tmp;
( *a )[0] = 10;
// or **a = 10;
printf("inside func= %d \n", ( *a )[0] );
}
return success;
}
而且函数可以这样调用
if ( padd( &pA () ) printf("outside func= %d",pA[0]);
注意调用realloc
你应该使用一个中间变量,因为通常函数可以return一个空指针。所以用空指针重新分配原始指针会导致指针的原始值丢失。
另外,当不再需要时,您应该释放所有动态分配的内存
free( pA );
如果realloc
不能扩展缓冲区,它将分配一个新缓冲区,将旧缓冲区的内容复制到它,释放旧缓冲区,并return地址新缓冲区的(或者 NULL
如果它不能满足请求);因此,a
的值可以在 padd
中改变。但是,该更改仅适用于形式参数 a
- 实际参数 pA
不受影响。
根据行为,它 看起来 如果您分配 d
,它会在 pA
之后立即分配,这样 pA
可以' 就地扩展,因此 realloc
正在创建一个新缓冲区并释放旧缓冲区,并且旧缓冲区在 main
.printf
语句之前被覆盖。
您需要编写 padd
,这样对 a
的任何更改都会反映在 pA
中 - return [=] 的(可能是新的)值14=] 或将指针传递给 pA
:
void padd( int **a )
{
size_t sizes = 10 * sizeof (int); // see note 1
int *tmp = realloc( *a, sizes ); // see note 2
if ( tmp )
{
*a = tmp;
(*a)[0] = 10;
printf( "Inside func, (*a)[0] = %d\n", (*a)[0] );
}
else
{
printf ( "Inside func, realloc failed!\n" );
}
}
你会称它为
padd( &pA );
注 1:sizeof
的类型为 size_t
,而不是 int
。
注2:由于realloc
可能returnNULL
,总是将结果赋给一个临时值,并在赋值前检查它回到原来的变量,否则你 运行 失去对你已经分配的内存的访问的风险。此外,强制转换为 void *
是不必要的且令人困惑,因为您将结果分配给 int *
变量。除非您将此代码编译为 C++ 或在 ancient K&R C 编译器下,否则请完全关闭强制转换 - 否则,您的强制转换必须与您正在分配的事物的类型相匹配至,在本例中为 int *
.