在未初始化的指针上使用 Malloc/Realloc 时出现段错误
SegFault while using Malloc/Realloc on an uninitialized pointer
我正在研究 "light drone simulator"(在 C 中),我的任务之一是在我左键单击地图时添加静态目标。到目前为止,一切都很好。
问题是,我不想创建一个具有给定大小的矩阵作为全局变量,而是想从一个未初始化的指针开始,一旦我左键单击,我就会重新分配新内存,以便始终有足够的可用内存,但不会更多.另外,我的 "matrix" 应该有 4 列用于 3D 坐标,1 列用于 "activation"。
这是我的部分代码:
/* Main program */
double **TargetsArray;
int main(int argc, char *argv[]) {
/* Call of model-specific mouse handling function */
HandleSpecialMouseEvent(button, state, x, y, &ActualFlockingParams,
&ActualVizParams, TargetPosition, TargetsArray, Modder);
}
void HandleSpecialMouseEvent(int button,
int state,
int x,
int y,
flocking_model_params_t * FlockingParams,
vizmode_params_t * VizParams,
double * CoordTarg, double ** TargetsArray,
const int Modifier) {
static int cnt = 0;
if (button == GLUT_LEFT && state == GLUT_DOWN && Modifier == GLUT_ACTIVE_ALT) {
FillVect(CoordTarg, MouseCoordToReal_2D(x, VizParams->MapSizeXY,
VizParams->Resolution) + VizParams->CenterX, -MouseCoordToReal_2D(y, VizParams->MapSizeXY,
VizParams->Resolution) + VizParams->CenterY, 0);
printf("%d\n", cnt);
if (cnt == 0) {
TargetsArray = malloc( sizeof *TargetsArray );
TargetsArray[cnt] = malloc( sizeof **TargetsArray * 4);
printf("Hello");
TargetsArray[cnt][0] = CoordTarg[0];
TargetsArray[cnt][1] = CoordTarg[1];
TargetsArray[cnt][2] = 0;
TargetsArray[cnt][3] = 1;
cnt += 1;
}
else {
printf("Youhou");
TargetsArray = realloc(TargetsArray, sizeof *TargetsArray * (cnt + 1) );
TargetsArray[cnt] = malloc( sizeof **TargetsArray * 4);
TargetsArray[cnt][0] = CoordTarg[0];
TargetsArray[cnt][1] = CoordTarg[1];
TargetsArray[cnt][2] = 0;
TargetsArray[cnt][3] = 1;
TargetsArray[cnt - 1][3] = 0;
cnt += 1;
}
// for (int j = 0; j < cnt; j++) {
// for (int i = 0; i < 4; i++) {
// printf("%f\t", TargetsArray[j][i]);
// }
// printf("\n");
// }
}
}
我通常会遇到两种类型的错误:
0
Hello1
Youhou2
Erreur de segmentation (core dumped)
OR
0
Hello1
free(): invalid next size (fast)
Abandon (core dumped)
我知道有更简单的方法可以做到这一点,但我真的很想了解为什么这不起作用。我很确定这是由于我使用 malloc 和 realloc 的方式造成的,但我也不明白为什么在第一个 "loop" 程序不会进入 if 语句,而它会打印“0”,然后为什么它会在打印计数器 (cnt) 之前打印 "Hello"?
我希望我提供了足够的代码让您理解我的问题,但如果缺少某些内容,请告诉我。
谢谢!!
关于malloc,realloc的行,请检查你要求的内存是否可用,是否可以分配,都return和NULL
以防出错。
只需检查是否有足够的内存,并且可以为两个 alloc 调用分配内存,如下所示:
TargetsArray = malloc( sizeof *TargetsArray );
if(TargetsArray == NULL){
//oh! not enough mem, or whatever...
}
//...
void* TargetsArray_ra = realloc(TargetsArray, sizeof(*TargetsArray) * (cnt + 1) );
if(TargetsArray_ra == NULL){
//oh! could not realloc
//if you wish to return, don't forget to free up the TargetsArray
if(TargetsArray != NULL){free(TargetsArray);TargetsArray=NULL;}
//return;
}else{//when realloc was success
TargetsArray = TargetsArray_ra ;
}
对 TargetsArray[cnt] = malloc( sizeof **TargetsArray * 4);
进行同样的检查,确保在访问它之前需要一个正确的非 NULL
ptr
那些 if-else 块也有点相同,除了最后一个语句,除此之外当你调试代码时,你在哪一行得到段错误?
您确定传递的 CoordTarg
不是 NULL
,并且长度合适?
FillVect
函数呢?它按预期工作吗?
您需要更改函数的参数 TargetsArray
以便它指向全局变量而不是仅存储相同的值。
主程序:
double **TargetsArray;
int main(int argc, char *argv[]) {
/* Call of model-specific mouse handling function */
HandleSpecialMouseEvent(button, state, x, y, &ActualFlockingParams,
&ActualVizParams, TargetPosition, &TargetsArray, Modder);
}
void HandleSpecialMouseEvent(int button,
int state,
int x,
int y,
flocking_model_params_t * FlockingParams,
vizmode_params_t * VizParams,
double * CoordTarg, double *** TargetsArray,
const int Modifier) {
static int cnt = 0;
if (button == GLUT_LEFT && state == GLUT_DOWN && Modifier == GLUT_ACTIVE_ALT) {
FillVect(CoordTarg, MouseCoordToReal_2D(x, VizParams->MapSizeXY,
VizParams->Resolution) + VizParams->CenterX, -MouseCoordToReal_2D(y, VizParams->MapSizeXY,
VizParams->Resolution) + VizParams->CenterY, 0);
printf("%d\n", cnt);
if (cnt == 0) {
*TargetsArray = malloc( sizeof **TargetsArray );
(*TargetsArray)[cnt] = malloc( sizeof ***TargetsArray * 4);
printf("Hello\n");
(*TargetsArray)[cnt][0] = CoordTarg[0];
(*TargetsArray)[cnt][1] = CoordTarg[1];
(*TargetsArray)[cnt][2] = 0;
(*TargetsArray)[cnt][3] = 1;
cnt += 1;
}
else {
printf("Youhou");
*TargetsArray = realloc(*TargetsArray, sizeof **TargetsArray * (cnt + 1) );
(*TargetsArray)[cnt] = malloc( sizeof ***TargetsArray * 4);
(*TargetsArray)[cnt][0] = CoordTarg[0];
(*TargetsArray)[cnt][1] = CoordTarg[1];
(*TargetsArray)[cnt][2] = 0;
(*TargetsArray)[cnt][3] = 1;
(*TargetsArray)[cnt - 1][3] = 0;
cnt += 1;
}
// for (int j = 0; j < cnt; j++) {
// for (int i = 0; i < 4; i++) {
// printf("%f\t", *TargetsArray[j][i]);
// }
// printf("\n");
// }
}
}
注意:括号非常重要
每次重新分配内存时,都会在 TargetsArray
中存储一个新的内存地址。由于您要更改函数内部的值,因此需要为函数提供变量 TargetsArray
的地址。其他方式你只会将重新分配的地址存储在函数的本地 TargetsArray
.
我正在研究 "light drone simulator"(在 C 中),我的任务之一是在我左键单击地图时添加静态目标。到目前为止,一切都很好。 问题是,我不想创建一个具有给定大小的矩阵作为全局变量,而是想从一个未初始化的指针开始,一旦我左键单击,我就会重新分配新内存,以便始终有足够的可用内存,但不会更多.另外,我的 "matrix" 应该有 4 列用于 3D 坐标,1 列用于 "activation"。
这是我的部分代码:
/* Main program */
double **TargetsArray;
int main(int argc, char *argv[]) {
/* Call of model-specific mouse handling function */
HandleSpecialMouseEvent(button, state, x, y, &ActualFlockingParams,
&ActualVizParams, TargetPosition, TargetsArray, Modder);
}
void HandleSpecialMouseEvent(int button,
int state,
int x,
int y,
flocking_model_params_t * FlockingParams,
vizmode_params_t * VizParams,
double * CoordTarg, double ** TargetsArray,
const int Modifier) {
static int cnt = 0;
if (button == GLUT_LEFT && state == GLUT_DOWN && Modifier == GLUT_ACTIVE_ALT) {
FillVect(CoordTarg, MouseCoordToReal_2D(x, VizParams->MapSizeXY,
VizParams->Resolution) + VizParams->CenterX, -MouseCoordToReal_2D(y, VizParams->MapSizeXY,
VizParams->Resolution) + VizParams->CenterY, 0);
printf("%d\n", cnt);
if (cnt == 0) {
TargetsArray = malloc( sizeof *TargetsArray );
TargetsArray[cnt] = malloc( sizeof **TargetsArray * 4);
printf("Hello");
TargetsArray[cnt][0] = CoordTarg[0];
TargetsArray[cnt][1] = CoordTarg[1];
TargetsArray[cnt][2] = 0;
TargetsArray[cnt][3] = 1;
cnt += 1;
}
else {
printf("Youhou");
TargetsArray = realloc(TargetsArray, sizeof *TargetsArray * (cnt + 1) );
TargetsArray[cnt] = malloc( sizeof **TargetsArray * 4);
TargetsArray[cnt][0] = CoordTarg[0];
TargetsArray[cnt][1] = CoordTarg[1];
TargetsArray[cnt][2] = 0;
TargetsArray[cnt][3] = 1;
TargetsArray[cnt - 1][3] = 0;
cnt += 1;
}
// for (int j = 0; j < cnt; j++) {
// for (int i = 0; i < 4; i++) {
// printf("%f\t", TargetsArray[j][i]);
// }
// printf("\n");
// }
}
}
我通常会遇到两种类型的错误:
0
Hello1
Youhou2
Erreur de segmentation (core dumped)
OR
0
Hello1
free(): invalid next size (fast)
Abandon (core dumped)
我知道有更简单的方法可以做到这一点,但我真的很想了解为什么这不起作用。我很确定这是由于我使用 malloc 和 realloc 的方式造成的,但我也不明白为什么在第一个 "loop" 程序不会进入 if 语句,而它会打印“0”,然后为什么它会在打印计数器 (cnt) 之前打印 "Hello"?
我希望我提供了足够的代码让您理解我的问题,但如果缺少某些内容,请告诉我。
谢谢!!
关于malloc,realloc的行,请检查你要求的内存是否可用,是否可以分配,都return和NULL
以防出错。
只需检查是否有足够的内存,并且可以为两个 alloc 调用分配内存,如下所示:
TargetsArray = malloc( sizeof *TargetsArray );
if(TargetsArray == NULL){
//oh! not enough mem, or whatever...
}
//...
void* TargetsArray_ra = realloc(TargetsArray, sizeof(*TargetsArray) * (cnt + 1) );
if(TargetsArray_ra == NULL){
//oh! could not realloc
//if you wish to return, don't forget to free up the TargetsArray
if(TargetsArray != NULL){free(TargetsArray);TargetsArray=NULL;}
//return;
}else{//when realloc was success
TargetsArray = TargetsArray_ra ;
}
对 TargetsArray[cnt] = malloc( sizeof **TargetsArray * 4);
进行同样的检查,确保在访问它之前需要一个正确的非 NULL
ptr
那些 if-else 块也有点相同,除了最后一个语句,除此之外当你调试代码时,你在哪一行得到段错误?
您确定传递的 CoordTarg
不是 NULL
,并且长度合适?
FillVect
函数呢?它按预期工作吗?
您需要更改函数的参数 TargetsArray
以便它指向全局变量而不是仅存储相同的值。
主程序:
double **TargetsArray;
int main(int argc, char *argv[]) {
/* Call of model-specific mouse handling function */
HandleSpecialMouseEvent(button, state, x, y, &ActualFlockingParams,
&ActualVizParams, TargetPosition, &TargetsArray, Modder);
}
void HandleSpecialMouseEvent(int button,
int state,
int x,
int y,
flocking_model_params_t * FlockingParams,
vizmode_params_t * VizParams,
double * CoordTarg, double *** TargetsArray,
const int Modifier) {
static int cnt = 0;
if (button == GLUT_LEFT && state == GLUT_DOWN && Modifier == GLUT_ACTIVE_ALT) {
FillVect(CoordTarg, MouseCoordToReal_2D(x, VizParams->MapSizeXY,
VizParams->Resolution) + VizParams->CenterX, -MouseCoordToReal_2D(y, VizParams->MapSizeXY,
VizParams->Resolution) + VizParams->CenterY, 0);
printf("%d\n", cnt);
if (cnt == 0) {
*TargetsArray = malloc( sizeof **TargetsArray );
(*TargetsArray)[cnt] = malloc( sizeof ***TargetsArray * 4);
printf("Hello\n");
(*TargetsArray)[cnt][0] = CoordTarg[0];
(*TargetsArray)[cnt][1] = CoordTarg[1];
(*TargetsArray)[cnt][2] = 0;
(*TargetsArray)[cnt][3] = 1;
cnt += 1;
}
else {
printf("Youhou");
*TargetsArray = realloc(*TargetsArray, sizeof **TargetsArray * (cnt + 1) );
(*TargetsArray)[cnt] = malloc( sizeof ***TargetsArray * 4);
(*TargetsArray)[cnt][0] = CoordTarg[0];
(*TargetsArray)[cnt][1] = CoordTarg[1];
(*TargetsArray)[cnt][2] = 0;
(*TargetsArray)[cnt][3] = 1;
(*TargetsArray)[cnt - 1][3] = 0;
cnt += 1;
}
// for (int j = 0; j < cnt; j++) {
// for (int i = 0; i < 4; i++) {
// printf("%f\t", *TargetsArray[j][i]);
// }
// printf("\n");
// }
}
}
注意:括号非常重要
每次重新分配内存时,都会在 TargetsArray
中存储一个新的内存地址。由于您要更改函数内部的值,因此需要为函数提供变量 TargetsArray
的地址。其他方式你只会将重新分配的地址存储在函数的本地 TargetsArray
.