Falha de segmentação em grandes tamanhos de matriz

116

O código a seguir me dá uma falha de segmentação quando executado em uma máquina de 2 Gb, mas funciona em uma máquina de 4 GB.

int main()
{
   int c[1000000];
   cout << "done\n";
   return 0;
}

O tamanho do array é de apenas 4Mb. Existe um limite para o tamanho de uma matriz que pode ser usada em c ++?

Mayank
fonte

Respostas:

130

Você provavelmente está apenas tendo um estouro de pilha aqui. A matriz é muito grande para caber no espaço de endereço da pilha do seu programa.

Se você alocar a matriz no heap, não terá problemas, supondo que sua máquina tenha memória suficiente.

int* array = new int[1000000];

Mas lembre-se de que isso exigirá que você entre delete[]no array. Uma solução melhor seria usar std::vector<int>e redimensionar para 1.000.000 de elementos.

Charles Salvia
fonte
3
Obrigado pela resposta, mas você poderia me explicar por que os arrays são alocados na pilha e por que não na memória do programa principal.
Mayank
18
O código fornecido é alocado na pilha porque é especificado como uma matriz com um número constante de elementos em tempo de compilação. Os valores são colocados apenas na pilha com malloc, new, etc.
Seth Johnson
6
Todas as variáveis ​​automáticas são alocadas na pilha. Se você olhar para o disasseble, verá o tamanho das variáveis ​​locais subtraídas do ponteiro da pilha. Quando você chama malloc ou calloc ou qualquer uma das funções de memória, as funções vão e encontram blocos de memória grandes o suficiente para satisfazer sua solicitação.
executado em
@Charles, por que poderíamos alocar mais memória da pilha, não da pilha? do meu entendimento, a pilha e o heap se movem na direção oposta no espaço de endereço alocado na memória.
saurabh agarwal
2
@saurabhagarwal A pilha não se move. Não é nem mesmo uma região de memória contígua. O alocador simplesmente retorna um bloco de memória livre que se ajusta aos seus requisitos de tamanho. O que e onde estão a pilha e o heap?
phuclv
56

Em C ou C ++, os objetos locais geralmente são alocados na pilha. Você está alocando uma grande matriz na pilha, mais do que a pilha pode suportar, então você está recebendo um stackoverflow.

Não o aloque localmente na pilha, use algum outro lugar ao invés. Isso pode ser obtido tornando o objeto global ou alocando-o no heap global . Variáveis ​​globais estão bem, se você não usar o de nenhuma outra unidade de compilação. Para garantir que isso não aconteça por acidente, adicione um especificador de armazenamento estático, caso contrário, apenas use o heap.

Isso será alocado no segmento BSS, que faz parte do heap:

static int c[1000000];
int main()
{
   cout << "done\n";
   return 0;
}

Isso será alocado no segmento DATA, que também faz parte do heap:

int c[1000000] = {};
int main()
{
   cout << "done\n";
   return 0;
}

Isso será alocado em algum local não especificado no heap:

int main()
{
   int* c = new int[1000000];
   cout << "done\n";
   return 0;
}
Gunther Piez
fonte
Se você usar o terceiro padrão, alocando no heap, não se esqueça de deletar [] o ponteiro em algum estágio ou você perderá memória. Ou procure dicas inteligentes.
davidA,
8
@meowsqueak Claro que é uma boa prática para deletequalquer lugar onde você alocar new. Mas se você tiver certeza de alocar memória apenas uma vez (como no principal), ela não é estritamente necessária - a memória é garantida para ser liberada na saída de principal, mesmo sem explícita delete.
Gunther Piez,
'at'drhirsch (como você faz um personagem at?) - sim, comentário justo. Como o OP parece novo para a linguagem, eu só queria ter certeza de que eles, e qualquer outra pessoa que visse sua boa resposta, estavam cientes das implicações da terceira opção, se usada de maneira geral.
davidA,
15

Além disso, se estiver executando na maioria dos sistemas UNIX e Linux, você pode aumentar temporariamente o tamanho da pilha com o seguinte comando:

ulimit -s unlimited

Mas tenha cuidado, a memória é um recurso limitado e com grande poder vêm grandes responsabilidades :)

RSFalcon7
fonte
1
Esta é a solução, mas aconselho a todos que sejam extremamente cautelosos ao remover os limites padrão do tamanho da pilha do programa. Você experimentará não apenas uma queda severa de desempenho, mas seu sistema poderá travar. Por exemplo, tentei classificar um array com 16.000.000 de elementos inteiros com quicksort em uma máquina com 4 GB de RAM e meu sistema quase morreu. LOL
rbaleksandar
@rbaleksandar Eu acho que seu programa de ~ 16 MB quase mata sua máquina porque você estava trabalhando com várias cópias do array (pode ser uma por chamada de função?) tente uma implementação com mais memória;)
RSFalcon7
Tenho quase certeza de que o manuseio do array está bem, já que estou passando por referência e não por valor. A mesma coisa acontece com o bubblesort. Inferno, mesmo que minha implementação do quicksort seja uma merda, o bubblesort é algo que você não pode implementar incorretamente. LOL
rbaleksandar
LOL, você pode tentar o tipo radix ou simplesmente usar std :: sort :)
RSFalcon7
1
Sem chance. É uma tarefa de laboratório. : D
rbaleksandar
3

Seu array está sendo alocado na pilha, neste caso, tente alocar um array do mesmo tamanho usando alloc.

repetir
fonte
3

Porque você armazena a matriz na pilha. Você deve armazená-lo na pilha. Veja este link para entender o conceito de heap e pilha.

Narek
fonte