variable una tamaño segmentation objetos matriz llenar generado dinámica dinamicos dinamica crear bidimensionales arreglos c++ linux stack-overflow

una - matriz dinamica c++



La matriz 2D grande da una falla de segmentación (7)

¡Me parece que tienes un desbordamiento de pila honesto-a-Spolsky!

Intenta compilar tu programa con la opción gcc -fstack-check. Si sus arreglos son demasiado grandes para asignar en la pila, obtendrá una excepción StorageError.

Sin embargo, creo que es una buena apuesta, ya que 5000 * 500 * 3 dobles (8 bytes cada uno) llegan a unos 60 megas, ninguna plataforma tiene suficiente pila para eso. Tendrás que asignar tus matrices grandes en el montón.

Estoy escribiendo un código C ++ en Linux, donde he declarado algunas matrices 2D como esta:

double x[5000][500], y[5000][500], z[5000][500];

Durante la compilación no hay error. Cuando lo ejecuto dice "falla de segmentación".

Cuando reduzco el tamaño de la matriz de 5000 a 50, el programa funciona bien. ¿Cómo puedo protegerme contra este problema?


Es posible que desee probar y utilizar Boost.Multi_array

typedef boost::multi_array<double, 2> Double2d; Double2d x(boost::extents[5000][500]); Double2d y(boost::extents[5000][500]); Double2d z(boost::extents[5000][500]);

La porción de memoria grande real se asignará en el montón y se desasignará automáticamente cuando sea necesario.


Estas matrices están en la pila. Las pilas son bastante limitadas en tamaño. Probablemente te encuentras con un ... desbordamiento de pila :)

Si quieres evitar esto, debes ponerlos en la tienda gratuita:

double* x =new double[5000*5000];

Pero es mejor que empieces con el buen hábito de usar los contenedores estándar, que envuelven todo esto para ti:

std::vector< std::vector<int> > x( std::vector<int>(500), 5000 );

Además: incluso si la pila se ajusta a las matrices, aún necesita espacio para que las funciones coloquen sus marcos.


Otra solución a las anteriores sería ejecutar un

ulimit -s stack_area

para ampliar la pila máxima.


Si su programa se ve así ...

int main(int, char **) { double x[5000][500],y[5000][500],z[5000][500]; // ... return 0; }

... entonces estás desbordando la pila. La forma más rápida de solucionar esto es agregar la palabra estática .

int main(int, char **) { static double x[5000][500],y[5000][500],z[5000][500]; // ... return 0; }

La segunda forma más rápida de solucionar esto es mover la declaración fuera de la función:

double x[5000][500],y[5000][500],z[5000][500]; int main(int, char **) { // ... return 0; }

La tercera forma más rápida de solucionar este problema es asignar la memoria en el montón:

int main(int, char **) { double **x = new double*[5000]; double **y = new double*[5000]; double **z = new double*[5000]; for (size_t i = 0; i < 5000; i++) { x[i] = new double[500]; y[i] = new double[500]; z[i] = new double[500]; } // ... for (size_t i = 5000; i > 0; ) { delete[] z[--i]; delete[] y[i]; delete[] x[i]; } delete[] z; delete[] y; delete[] x; return 0; }

La cuarta forma más rápida es asignarlos en el montón usando std :: vector. Hay menos líneas en su archivo pero más líneas en la unidad de compilación, y debe pensar en un nombre significativo para sus tipos de vectores derivados o meterlos en un espacio de nombres anónimo para que no contaminen el espacio de nombres global:

#include <vector> using std::vector namespace { struct Y : public vector<double> { Y() : vector<double>(500) {} }; struct XY : public vector<Y> { XY() : vector<Y>(5000) {} } ; } int main(int, char **) { XY x, y, z; // ... return 0; }

La quinta forma más rápida es asignarlos en el montón, pero use plantillas para que las dimensiones no estén tan alejadas de los objetos:

include <vector> using namespace std; namespace { template <size_t N> struct Y : public vector<double> { Y() : vector<double>(N) {} }; template <size_t N1, size_t N2> struct XY : public vector< Y<N2> > { XY() : vector< Y<N2> > (N1) {} } ; } int main(int, char **) { XY<5000,500> x, y, z; XY<500,50> mini_x, mini_y, mini_z; // ... return 0; }

La forma más eficaz es asignar las matrices bidimensionales como matrices unidimensionales y luego utilizar la aritmética de índice.

Todo lo anterior supone que tiene alguna razón, buena o mala, por querer crear su propio mecanismo de matriz multidimensional. Si no tiene ninguna razón y espera volver a utilizar matrices multidimensionales, considere la posibilidad de instalar una biblioteca:


Su declaración debe aparecer en el nivel superior, fuera de cualquier procedimiento o método.

Con mucho, la forma más fácil de diagnosticar un error de seguridad en código C o C ++ es usar valgrind . Si uno de sus arreglos tiene la culpa, valgrind señalará exactamente dónde y cómo. Si la culpa está en otra parte, también te lo dirá.

valgrind se puede usar en cualquier binario x86, pero le dará más información si compila con gcc -g .


Una reserva acerca de usar siempre vector: por lo que yo entiendo, si abandonas el final de la matriz, simplemente asigna una matriz más grande y copia todo lo que podría crear errores sutiles y difíciles de encontrar cuando realmente estás tratando de trabajar con ellos. una matriz de tamaño fijo. Al menos con una matriz real, segregarás si te alejas del final haciendo que el error sea más fácil de detectar.

#include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { typedef double (*array5k_t)[5000]; array5k_t array5k = calloc(5000, sizeof(double)*5000); // should generate segfault error array5k[5000][5001] = 10; return 0; }