Переполнение стека C ++ - PullRequest
6 голосов
/ 03 июня 2011

Это мой код. Когда я обращаюсь к массиву dtr в функции initImg, это дает исключение переполнения стека. В чем может быть причина?

#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;
}

Ответы [ 8 ]

17 голосов
/ 03 июня 2011

Это:

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

Создает каждый массив размером 4 *1000* 1000 ~ 4 МБ в стек. Размер стека ограничен и обычно составляет менее 4 МБ. Не делайте этого, создайте массивы в куче, используя new.

int *image = new int[W*H];
float *dtr = new float[W*H];
10 голосов
/ 03 июня 2011

Ваш стек, вероятно, недостаточно велик, чтобы вместить миллион целых и миллион флотаций (8 МБ). Поэтому, как только вы попытаетесь получить доступ за пределы стека, ваша операционная система выдаст вам ошибку. Объекты или массивы выше определенного размера должны быть размещены в куче - предпочтительно используя самоуправляемый класс самоконтроля границ, такой как std::vector - конкретный размер зависит от вашей реализации.

3 голосов
/ 03 июня 2011

Помимо переполнения стека, у вас есть еще одна проблема - та, которая маскируется вашими определениями 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 голосов
/ 03 июня 2011

Вы создаете гигантские массивы в стеке.Просто используйте std::vector вместо:

std::vector<int> image(W*H);
std::vector<float> dtr(W*H);
1 голос
/ 25 сентября 2017

Ваш стек заполнен.Вы можете выделить память в куче или увеличить объем памяти стека.Из того, что я знаю, максимальный размер составляет около 8 МБ, но это не очень хорошая идея.Лучшее решение - использовать выделение кучи или некоторые контейнеры (vector), доступные в std.

0 голосов
/ 03 октября 2012

Вы пытаетесь выделить память из стека.максимальный объем памяти, который может быть выделен с использованием стека, зависит от компилятора.Поэтому попробуйте что-то вроде этого, чтобы избежать такого рода исключений.

#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; 
}

Вы также можете использовать new вместо malloc для выделения памяти из кучи ...

0 голосов
/ 03 июня 2011

Ваш компилятор определит размер стека. Чтобы обойти это, нужно динамически распределять массивы с помощью std :: vector array_one (W * H).

0 голосов
/ 03 июня 2011

В конечном итоге вы получите

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

Это намного больше, чем вы выделили.

...