在C中尝试用realloc扩展数组时出现分段错误



我的代码运行良好,最多3次迭代都能得到正确的结果。然而,当我尝试运行以下代码时,我在3次迭代后出现了分段错误:

int addNode(double* distNewNode,int placeCount, int* phi,double* lambda)
{
int i ;
int nextPlaceCount = placeCount+1;
//int nodeCount = placeCount -1;
phi= realloc(phi,nextPlaceCount*sizeof(int));
lambda = realloc(lambda,nextPlaceCount*sizeof(double)); //This line throws the error
phi[placeCount] = placeCount;
lambda[placeCount] = DBL_MAX;
for (i = 0;i < placeCount; i++)
if (lambda[i] >= distNewNode[i])
{
if (lambda[i] <= distNewNode[phi[i]])
distNewNode[phi[i]] = lambda[i];
lambda[i] = distNewNode[i];
phi[i] = placeCount;
}
else if (distNewNode[i] < distNewNode[phi[i]])
distNewNode[phi[i]] = distNewNode[i];
for (i = 0;i < placeCount;i++)
if(lambda[i] >= lambda[phi[i]] )
phi[i] = placeCount;
return 1;
}

以下是我如何调用addNode()函数:

int main()
{
//Create distMat here
int* phi;
phi = (int*)malloc(1);
phi[0] = 1;
//phi[1] = 1;
double* lambda;
lambda = (double*)malloc(1);
//lambda[0] = 1.2;
lambda[0] = DBL_MAX;
int isNodeAdded;
for (int  placeCount=0; placeCount < 10;placeCount++)
{
double* temp =(double*) malloc(placeCount);
for (int j= 0;j < placeCount ;j++)
{
temp[j] = distMat[placeCount][j];
}
isNodeAdded = addNode(temp,placeCount,phi,lambda);
cout << "isNodeAdded: "<<isNodeAdded << endl;
free(temp);
for (int i=0;i < placeCount ;i++)
{
printf("Node= %d Pi = %d Lambda = %f n",i,phi[i],lambda[i]);
}
}
}

我的输出是:

isNodeAdded: 1
isNodeAdded: 1
Node= 0 Pi = 1 Lambda = 1.200000 
isNodeAdded: 1
Node= 0 Pi = 1 Lambda = 1.200000 
Node= 1 Pi = 2 Lambda = 3.400000 
isNodeAdded: 1
The program has unexpectedly finished.

问题是通过值传递参数phi,这意味着它的值被复制到函数局部变量phi中,并且与所有局部变量一样,当函数返回并且函数内部对它的所有更改都丢失时,phi将超出范围。

如果函数addNode在C源文件中,则不能通过引用传递,因为C不支持它,因此必须通过向指针变量传递指针来模拟它,即在main函数中,您需要传递&phi,并将函数修改为采用int **phi,并根据需要适当地取消对变量的引用。

另一方面,如果addNode在C++源文件中,那么您只需将参数更改为int *&phi,就会有一个引用变量,它将引用作为main函数参数传递的原始变量。

您还有另一个问题,它将在main函数中为您提供未定义的行为:

phi = (int*)malloc(1);
phi[0] = 1;

在这里,您分配一个字节,并将其用作int,通常为四个字节。


在一个无关的注释中,您不应该将realloc的结果重新分配回作为参数传递的变量。想想如果realloc返回NULL会发生什么。原始指针仍然有效,但如果重新分配它,将丢失指针,从而导致内存泄漏。

最新更新