简体   繁体   English

C中二维数组的分割错误

[英]Segmentation Fault on 2D array in C

I'm making what we call an integral image, but I have a problem. 我正在制作所谓的完整图像,但是我有一个问题。 When I reach a certain number I have an Segmentation fault. 当我达到一定数量时,我会遇到细分错误。 The image is 273*273 it works, 274*274 not working. 图像大小为273 * 273,274 * 274不工作。 So i tried to Malloc my double array. 所以我试图Malloc我的双数组。 Same. 相同。 I've read that arrays in a function are in the Stack, and the stack has small space. 我读过一个函数中的数组在堆栈中,并且堆栈的空间很小。 How can I make my array declared in the memory? 如何使我的数组在内存中声明?

I am using C99 and SDL: 我正在使用C99和SDL:

void integral_img(SDL_Surface * img)
{
    int **M;

    M = malloc(img->w * sizeof(int *));
    for (int i = 0; i < img->w; i++)
    {
        M[i] = malloc(img->h * sizeof(int));
    }
    int sum_int = 0;
    Uint8 sum = 0;

    for (int i = 0; i < img->h; i++)
    {
        for (int j = 0; j < img->w; j++)
        {
            SDL_GetRGB(getpixel(img, i, j), img->format, &sum, &sum, &sum);

            if (i == 0 && j == 0)
                sum_int = (int)sum;
            if (i == 0 && j > 0)
                sum_int = (int)sum + M[i][j - 1];
            if (j == 0 && i > 0)
                sum_int = (int)sum + M[i - 1][j];
            if (i > 0 && j > 0)
                sum_int = (int)sum + M[i - 1][j] + M[i][j - 1] - M[i - 1][j - 1];
            M[i][j] = sum_int;
        }
    }
}
  • You are allocating a pointer-based lookup table, not a 2D array. 您正在分配基于指针的查找表,而不是2D数组。 It will work, but it is wide-spread incorrect practice: it makes the program needlessly slow for no gain. 它将起作用,但是它是广泛的不正确的做法:它使程序不必要地变慢而毫无收获。 Consider using a 2D array instead: 考虑改用2D数组:

     int (*M)[w] = malloc( sizeof(int[h][w]) ); ... free(M); 
  • One bug is here: 一个错误在这里:

     M = malloc(img->w * sizeof(int *)); for (int i = 0; i < img->w; i++) { M[i] = malloc(img->h * sizeof(int)); } 

    Here you declare the inner-most dimension of your lookup table to be w , width. 在这里,您将查找表的最内部尺寸声明为w ,width。

    But later on 但是后来

     for (int i = 0; i < img->h; i++) { for (int j = 0; j < img->w; j++) ... M[i][j] = sum_int; 

    you say that the inner-most dimension is h , height. 您说最里面的尺寸是h ,height。

  • Furthermore, your program leaks a lot of memory each time you call the function, since you don't free memory anywhere. 此外,由于您不会在任何地方释放内存,因此每次调用该函数时,程序都会泄漏大量内存。 In fact, you don't seem to even use the lookup table after filling it up. 实际上,您似乎在填满查询表后甚至没有使用它。

A simplified version of your code, modified to illustrate 2D array initialization and cleanup (you must free what you malloc): 代码的简化版本,经过修改以说明2D数组的初始化清除(您必须释放malloc的内容):

In short, your array initialization has to follow the way you create memory for row , column : 简而言之,数组初始化必须遵循为rowcolumn创建内存的方式:

typedef struct  {
    int h;
    int w;
}SDL_Surface;
//if you change your prototype to pass the initializer then you can
//free it in the calling function.  Otherwise, as written in your OP
//you will have a memory leak.
void integral_img(SDL_Surface * img, int **m);

int main(int argc, char* argv[])
{
    SDL_Surface img;
    int **M; 

    img.h = 100;
    img.w = 50;
    //create memory for array in calling function
    M = malloc(img.w * sizeof(int *));
    if(!M){ /*handle error and leave*/ }//test results of malloc
    for (int i = 0; i < img.w; i++)//... If you create space for w rows and h columns...
    {
        M[i] = malloc(img.h * sizeof(int));// note modified prototype
        if(!M[i]) {/*handle error and leave*/} //test results of malloc
    }

    integral_img(&img, M);

    //use img...

    //free M :(no memory leaks)

    for (int i = 0; i < img.w; i++)
    {
        if(M[i]) free(M[i]);
    }
    if(M) free(M);


    return 0;
}

void integral_img(SDL_Surface * img, int **m)
{


    for (int i = 0; i < img->w; i++)//... Then you must access w rows and h columns
    {                               // (w & h were reversed in your code)
        for (int j = 0; j < img->h; j++)
        {
            m[i][j] = (i+1)*(j+1);
        }
    }
}

i don't think that your code is bogus, but i am suspecting this line: 我不认为您的代码是伪造的,但我怀疑这行:

SDL_GetRGB(getpixel(img, i, j), img->format, &sum, &sum, &sum);

any way, why you have to allocate a 2D array such way? 无论如何,为什么您必须以这种方式分配2D数组? why not just one continues block? 为什么不止一个继续阻塞?

take a look to my code: 看一下我的代码:

void integral_img(SDL_Surface * img)
{
    #define _IDX(x,y) ((x)+((y)*cx))
   int cx=img->w,
        cy=img->h;
    int *M;

    //allocating only one continues block of memory
    M = malloc(cx*cy * sizeof(int ));
    if(!M){
        perror("not enough memory");
        exit(1);
    }

    int sum_int = 0;
    Uint8 t sum = 0;

    for (int i = 0; i < cy; i++)
    {
        for (int j = 0; j < cx; j++)
        {
            SDL_GetRGB(getpixel(img, i, j), img->format, &sum, &sum, &sum);

            if (i == 0 && j == 0)
                sum_int = (int)sum;
            if (i == 0 && j > 0)
                sum_int = (int)sum + M[_IDX(i,j - 1)];
            if (j == 0 && i > 0)
                sum_int = (int)sum + M[_IDX(i- 1,j )];
            if (i > 0 && j > 0)
                sum_int = (int)sum + M[_IDX(i- 1,j )] + M[_IDX(i,j - 1)] - M[_IDX(i- 1,j - 1)];
            M[_IDX(i,j )] = sum_int;
        }
    }

    // easy to free
    free(M); 
    return;
}

it is cleaner and uses less iterations on allocating and freeing memory. 它更干净,并且在分配和释放内存上使用的迭代次数更少。

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

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