简体   繁体   English

在未初始化的指针上使用 Malloc/Realloc 时出现段错误

[英]SegFault while using Malloc/Realloc on an uninitialized pointer

I'm working on a "light drone simulator" (in C) and one of my task is to add a static target when I left click on the map. So far so good.我正在开发一个“轻型无人机模拟器”(在 C 中),我的任务之一是在我左键单击 map 时添加一个 static 目标。到目前为止一切顺利。 The thing is that instead of creating a matrix with given sizes as a global variable I would like to start from an uninitialized pointer of pointer and as soon as I left click, I realloc new memory in order to always have enough memory available but not more.问题是,我不想创建一个具有给定大小的矩阵作为全局变量,而是想从一个未初始化的指针指针开始,一旦我左键单击,我就会重新分配新的 memory,以便始终有足够的 memory 可用但不会更多. Also my "matrix" should have 4 columns for 3D coordinates and 1 for "activation".另外,我的“矩阵”应该有 4 列用于 3D 坐标,1 列用于“激活”。

Here is a part of my code:这是我的代码的一部分:

/* 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");
            // }
        }


}

I usually get 2 types of errors:我通常会遇到两种类型的错误:

0
Hello1
Youhou2
Erreur de segmentation (core dumped)

OR 

0
Hello1
free(): invalid next size (fast)
Abandon (core dumped)

I know there are simplier ways of doing it but I'd really like to understand why this is not working.我知道有更简单的方法可以做到这一点,但我真的很想了解为什么这不起作用。 I'm pretty sure it is due to the way I use malloc and realloc but I also don't understand why in the first "loop" the program doesn't go into the if statement whereas it does print "0" and then why it prints "Hello" before printing the counter (cnt)?我很确定这是由于我使用mallocrealloc的方式,但我也不明白为什么在第一个“循环”中程序没有将 go 放入 if 语句中,而它打印“0”然后为什么它在打印计数器(cnt)之前打印“Hello”?

I hope I put enough code for you to understand my issue but please let me know if something is missing.我希望我为您提供了足够的代码来理解我的问题,但如果缺少某些内容,请告诉我。

Thanks !!谢谢 !!

The lines about malloc, and realloc, please check the memory you asked is available and could be allocated, both return a NULL in case of error.关于malloc和realloc, please check the lines about malloc, please check the memory is available and could be allocated, 都返回NULL以防错误。

Simply check if there are enough memory, and could be allocated, for both alloc calls, like following:只需检查是否有足够的 memory,并且可以分配给两个 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 ;
}

Same check for TargetsArray[cnt] = malloc( sizeof **TargetsArray * 4);同样检查TargetsArray[cnt] = malloc( sizeof **TargetsArray * 4); , make sure it takes a proper non- NULL ptr, before you access it , 在访问它之前确保它需要一个正确的非NULL ptr

Also those if-else blocks are kind of the same, except the last statement, besides that when you debug the code, at which line you get segfault?那些 if-else 块也有点相同,除了最后一个语句,除此之外当你调试代码时,你在哪一行得到段错误? You sure the passed CoordTarg is not NULL , and has proper length?您确定传递的CoordTarg不是NULL并且长度合适? What about FillVect func? FillVect函数呢? it's working as expected?它按预期工作吗?

You need to change your function's argument TargetsArray so that it points on the global variable and not only store the same value.您需要更改函数的参数TargetsArray ,以便它指向全局变量,而不仅仅是存储相同的值。

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\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");
            // }
        }


}

NOTE: Parentheses are very important注意:括号非常重要

In each time you reallocate memory, you are storing a new memory address in your TargetsArray .每次重新分配 memory 时,都会在 TargetsArray 中存储一个新的TargetsArray地址。 Since you're changing the value inside the function, you need to give your function the address of the variable TargetsArray .由于您正在更改 function 中的值,因此您需要为 function 提供变量TargetsArray的地址。 Other ways you will only store the reallocated address on the function's local TargetsArray .其他方式,您将仅将重新分配的地址存储在函数的本地TargetsArray

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM