2011-06-02 173 views
3

這是我的代碼。當我在initImg函數中訪問dtr數組時,它會產生堆棧溢出異常。可能是什麼原因?堆棧溢出C++

#define W 1000 
#define H 1000 
#define MAX 100000 
void initImg(int img[], float dtr[]) 
{ 
    for(int i=0;i<W;i++) 
     for(int j=0;j<H;j++) 
      img[i*W+j]=255; 

    for(int j=0;j<H;j++) 
    { 
     img[j] = 0; 
     img[W*(W-1)+j] = 0; 
    } 
    for(int i=0;i<W;i++) 
    { 
     img[i*W] = 0; 
     img[i*W+H-1] = 0; 
    } 
    for(int i=0;i<W;i++) 
     for(int j=0;j<H;j++) 
     { 
      if(img[i*W+j]==0) 
       dtr[i*W+j] = 0; // <------here 
      else 
       dtr[i*W+j] = MAX; // <------here 
     } 
} 
int main() 
{ 
    int image[W*H]; 
    float dtr[W*H]; 
    initImg(image,dtr); 
    return 0; 
} 

回答

13

此:

int image[W*H]; 
float dtr[W*H]; 

創建每一個4 * 1000 * 1000〜4 MB陣列入堆棧。堆棧空間有限,通常小於4 MB。不要這樣做,使用new在堆中創建陣列。

int *image = new int[W*H]; 
float *dtr = new float[W*H]; 
+12

呃使用'std :: vector'? – Puppy 2011-06-02 20:21:36

+0

@DeadMG:爲什麼要爲靜態數據使用動態結構?如果他所做的只是遍歷一個已知大小的數組 - 使用一個已知大小的數組,因爲它完全符合問題。 – Simon 2011-06-02 20:38:03

+4

@Simon:無論如何,你正在創建一個動態大小的數組,它恰好是已知的大小。除此之外,直接使用new將允許內存泄漏,並且對超出邊界訪問的調試支持很差/不支持。 'std :: vector 圖片(W * H);'以絕對安全的方式執行相同的功能。 – Puppy 2011-06-02 20:39:49

9

您的堆棧可能不足以容納一百萬個整數和一百萬個浮點數(8MB)。所以只要你嘗試訪問你的堆棧大小,你的操作系統就會給你一個錯誤。超過一定大小的對象或數組需要在堆上分配 - 最好使用自我管理的自我邊界檢查類,如std::vector - 具體大小取決於您的實現。

0

你最終會得到

dtr[W*W+j] = 0;   <------here 

這是遠遠超過你分配。

+0

-1不正確,他的循環是'我 2011-06-02 20:31:11

+0

@丹F - 你是正確的,但Bo的評論仍然揭示了海報的代碼 - 一個被W == H掩蓋的代碼。如果代替W = 100和H = 10,當i == W-1和j = 1時,總陣列爲1000個元素,但是(i * W + j)= 9909。 = H-1。這個問題在任何時候都會出現W> H,並且因爲環路向後(或者離開環路,索引計算需要改變)。 – mah 2011-06-02 20:45:52

0

您的編譯器將定義堆棧大小。解決這個問題的方法是使用std :: vector array_one(W * H)動態分配數組。

2

您正在堆棧上創建巨型數組。只需使用std::vector代替:

std::vector<int> image(W*H); 
std::vector<float> dtr(W*H); 
2

除了溢出堆棧,你有另一個問題 - 其中一個是由你的W和H.

for(int i=0;i<W;i++) 
    for(int j=0;j<H;j++) 
    { 
     if(img[i*W+j]==0) 
      dtr[i*W+j] = 0; // <------here 
     else 
      dtr[i*W+j] = MAX; // <------here 
    } 

你的i循環定義屏蔽應該算0到H-1,而不是W-1(並且j循環也應該交換)。否則,只有W == H時,您的代碼才能正常工作。如果WH你會超過你的緩衝區。

同樣的問題也存在於您的代碼示例的其他地方。

-2

您正試圖從堆棧分配內存。可以使用堆棧分配的最大內存依賴於編譯器。 所以嘗試這樣的事情來避免這種異常。

#include <stdlib.h> 
#define W 1000 
#define H 1000 
#define MAX 100000 
void initImg(int img[], float dtr[]) 
{ 
for(int i=0;i<W;i++) 
for(int j=0;j<H;j++) 
img[i*W+j]=255; 

for(int j=0;j<H;j++) 
{ 
img[j] = 0; 
img[W*(W-1)+j] = 0; 
} 
for(int i=0;i<W;i++) 
{ 
img[i*W] = 0; 
img[i*W+H-1] = 0; 
} 
for(int i=0;i<W;i++) 
for(int j=0;j<H;j++) 
{ 
if(img[i*W+j]==0) 
dtr[i*W+j] = 0; // <------here 
else 
dtr[i*W+j] = MAX; // <------here 
} 
} 
int main() 
{ 
int *image = (int*)malloc(4*W*H); //Malloc the memory....(Allocated from Heap..) 
float *dtr = (float*)malloc(4*W*H); 

if(image && dtr) //If none of the ptr is NULL. Means memory is allocated... 
{ 
initImg(image,dtr); 
} 
return 0; 
} 

您可以使用新的和替代使用malloc從堆中分配內存...

+0

-1這個問題已經超過一年了,已經接受了答案,除了已經在其他答案中的內容之外,你什麼都沒有增加。最後,您沒有更正您發佈的代碼中引發的索引問題[此處](http://stackoverflow.com/a/6220227/771663)。 – Massimiliano 2012-10-03 09:27:34

+0

我去@Massimiliano。除非你有新的建議,否則你不需要回答已經接受的問題。 – 2012-10-04 09:13:00

1

你的堆棧已滿。您可以在堆中分配內存或增加堆棧內存。從我所知道的最大尺寸大約是8MB,但這不是一個好主意。最好的解決方案是使用堆分配或std中提供的一些容器(向量)。