Fallo de segmentación en matrices de gran tamaño
El siguiente código me da un error de segmentación cuando lo ejecuto en una máquina de 2 Gb, pero funciona en una máquina de 4 GB.
int main()
{
int c[1000000];
cout << "done\n";
return 0;
}
El tamaño de la matriz es de sólo 4 Mb. ¿Existe un límite en el tamaño de una matriz que se puede utilizar en C++?
Probablemente estés recibiendo un desbordamiento de pila aquí. La matriz es demasiado grande para caber en la región de la pila de su programa; El límite de crecimiento de la pila suele ser de 8 MiB o 1 MiB para el código de espacio de usuario en la mayoría de los sistemas operativos de escritorio/servidor convencionales. (Las implementaciones normales de C++ utilizan la pila asm para el almacenamiento automático, es decir, static
matrices de variables no locales. Esto hace que la desasignación se realice de forma gratuita cuando las funciones regresan o una excepción se propaga a través de ellas).
Si asigna dinámicamente la matriz, debería estar bien, suponiendo que su máquina tenga suficiente memoria.
int* array = new int[1000000]; // may throw std::bad_alloc
Pero recuerde que esto requerirá que acceda a delete[]
la matriz manualmente para evitar pérdidas de memoria, incluso si su función sale a través de una excepción. Se desaconseja encarecidamente la creación/eliminación manual en C++ moderno, prefiera RAII .
Una mejor solución sería utilizarstd::vector<int> array
( cppreference ). Puedes reservar espacio para 1000000 elementos, si sabes cuánto crecerá. O incluso resize
construirlos de forma predeterminada (es decir, inicializar la memoria a cero, a diferencia de cuando se declara una matriz de estilo C simple sin inicializador), comostd::vector<int> array(1000000)
Cuando el std::vector
objeto sale del alcance, su destructor desasignará el almacenamiento por usted, incluso si eso sucede a través de una excepción en una función secundaria capturada por una función principal.
En C o C++ los objetos locales normalmente se asignan en la pila. Está asignando una matriz grande en la pila, más de la que la pila puede manejar, por lo que obtiene un desbordamiento de pila.
No lo asigne localmente en la pila, utilice otro lugar en su lugar. Esto se puede lograr haciendo que el objeto sea global o asignándolo en el montón global . Las variables globales están bien, si no las usas desde ninguna otra unidad de compilación. Para asegurarse de que esto no suceda por accidente, agregue un especificador de almacenamiento estático; de lo contrario, simplemente use el montón.
Esto se asignará en el segmento BSS, que es parte del montón. Dado que está en almacenamiento estático, se inicializa en cero si no se especifica lo contrario, a diferencia de las variables locales (almacenamiento automático), incluidas las matrices.
static int c[1000000];
int main()
{
cout << "done\n";
return 0;
}
Un inicializador distinto de cero hará que un compilador asigne en el segmento DATOS, que también forma parte del montón. (Y todos los datos para el inicializador de matriz ocuparán espacio en el ejecutable, incluidos todos los ceros finales implícitos, en lugar de solo un tamaño para inicio cero en el BSS)
int c[1000000] = {1, 2, 3};
int main()
{
cout << "done\n";
return 0;
}
Esto se asignará en alguna ubicación no especificada del montón:
int main()
{
int* c = new int[1000000]; // size can be a variable, unlike with static storage
cout << "done\n";
delete[] c; // dynamic storage needs manual freeing
return 0;
}
Además, si está ejecutando la mayoría de los sistemas UNIX y Linux, puede aumentar temporalmente el tamaño de la pila con el siguiente comando:
ulimit -s unlimited
Pero cuidado, la memoria es un recurso limitado y un gran poder conlleva grandes responsabilidades :)
Su matriz se está asignando en la pila; en este caso, intente asignar una matriz del mismo tamaño usando alloc.
Porque almacena la matriz en la pila. Deberías guardarlo en el montón. Consulte este enlace para comprender el concepto de montón y pila.