[英]Segmentation Fault on 2D array in C
我正在制作所謂的完整圖像,但是我有一個問題。 當我達到一定數量時,我會遇到細分錯誤。 圖像大小為273 * 273,274 * 274不工作。 所以我試圖Malloc我的雙數組。 相同。 我讀過一個函數中的數組在堆棧中,並且堆棧的空間很小。 如何使我的數組在內存中聲明?
我正在使用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;
}
}
}
您正在分配基於指針的查找表,而不是2D數組。 它將起作用,但是它是廣泛的不正確的做法:它使程序不必要地變慢而毫無收獲。 考慮改用2D數組:
int (*M)[w] = malloc( sizeof(int[h][w]) ); ... free(M);
一個錯誤在這里:
M = malloc(img->w * sizeof(int *)); for (int i = 0; i < img->w; i++) { M[i] = malloc(img->h * sizeof(int)); }
在這里,您將查找表的最內部尺寸聲明為w
,width。
但是后來
for (int i = 0; i < img->h; i++) { for (int j = 0; j < img->w; j++) ... M[i][j] = sum_int;
您說最里面的尺寸是h
,height。
此外,由於您不會在任何地方釋放內存,因此每次調用該函數時,程序都會泄漏大量內存。 實際上,您似乎在填滿查詢表后甚至沒有使用它。
代碼的簡化版本,經過修改以說明2D數組的初始化和清除(您必須釋放malloc的內容):
簡而言之,數組初始化必須遵循為row , column創建內存的方式:
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);
}
}
}
我不認為您的代碼是偽造的,但我懷疑這行:
SDL_GetRGB(getpixel(img, i, j), img->format, &sum, &sum, &sum);
無論如何,為什么您必須以這種方式分配2D數組? 為什么不止一個繼續阻塞?
看一下我的代碼:
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;
}
它更干凈,並且在分配和釋放內存上使用的迭代次數更少。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.