2011-06-02 226 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中提供的一些容器(向量)。