在未初始化的指针上使用 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)

我知道有更简单的方法可以做到这一点,但我真的很想了解为什么这不起作用。我很确定这是由于我使用 mallocrealloc 的方式造成的,但我也不明白为什么在第一个 "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.