segmentation que dumped c++ segmentation-fault

c++ - que - segmentation fault(core dumped) php



¿Qué puede causar fallas de segmentación en C++? (9)

Noté que no hay pregunta con una lista de causas comunes de fallas de segmentación en C ++, así que pensé en agregarlo.

Naturalmente, es Wiki de la comunidad, ya que no hay una respuesta correcta.

Creo que esto podría ser útil para los programadores más nuevos que aprenden C ++, pueden cerrarlo si no están de acuerdo.


Acceder a una matriz fuera de límites (Posible):

int ia[10]; ia[10] = 4; // Someone forgot that arrays are 0-indexed! Possible Segfault.


Desreferenciando punteros NULL.

#include <cstddef> //For NULL. int* p1 = NULL; //p1 points to no memory address *p1 = 3; //Segfault.


Intentando modificar literales de cadena:

char* mystr = "test"; mystr[2] = ''w'';

Esto PUEDE causar una falla de segmentación.


La desreferenciación de la memoria liberada podría causar una segfault.

SomeClass* someObject = new SomeClass(); delete someObject; someObject->someMethod(); //Could cause a segfault.


La respuesta obvia es "comportamiento indefinido", pero esto plantea la pregunta a un programador inexperto, y es menos probable que algunos tipos de comportamiento indefinido provoquen una falla de segmentación (u otro tipo de bloqueo) que otros. Las causas más frecuentes de las fallas de segmentación generalmente están relacionadas con el puntero: desreferenciar un puntero no inicializado, un puntero nulo o un puntero liberado previamente; acceder más allá del final (o antes del comienzo, pero eso es menos frecuente) de un objeto (matriz u otro); usar los resultados de un molde de puntero ilegal ( static_cast a un tipo derivado, cuando el objeto no tiene realmente ese tipo, o la mayoría reinterpret_cast ); etc.

Quizás el punto más importante a tener en cuenta aquí, sin embargo, es que, en general, no se garantiza que causen una falla de segmentación, y que a menudo, la falla de segmentación que causan solo ocurrirá algún tiempo después, en una operación completamente no relacionada. Por lo tanto, escribir más allá del final de una matriz local generalmente "funcionará", pero modificará lo que ocurra para seguir la matriz en la pila: alguna otra variable local (modificar el vptr de un objeto en la pila puede provocar un error de segmentación cuando intenta llamar a una función virtual en el objeto), el puntero de marco de la función de llamada (que probablemente causará una falla de segmentación en esa función, después de que haya regresado), o la dirección de retorno (que puede causar todo tipo de extraño comportamiento: una falla de segmentación o una trampa de instrucción ilegal son probablemente lo mejor que puede ocurrir). Escribir más allá del final de la memoria liberada, o a través de un puntero ya liberado, puede dañar el espacio de espacio libre, causando un error de segmentación en una asignación mucho (en algún momento, mucho) posterior o libre; también puede modificar algún otro objeto totalmente no relacionado, corrompiendo su vptr o algún otro puntero en el objeto, o solo algunos datos aleatorios; nuevamente, una falla de segmentación es probablemente el mejor resultado posible (es preferible continuar con los datos corruptos).


Muchas de las formas de ''segfault'' C ++ no están necesariamente garantizadas , de hecho, ese es el caso con la mayoría de los ejemplos publicados aquí. Es simplemente buena suerte (¡o mala suerte, dependiendo de cómo lo mires!) Si puedes realizar estas operaciones sin que se produzca un segfault.

Esa es en realidad una de las cosas en C ++ que lo separa de otros lenguajes; comportamiento indefinido Mientras que en Java o C # puede obtener una ''InvalidOperationException'' o similar, que se garantiza que ocurrirá cuando se realicen estas operaciones; en C ++, el estándar simplemente dice ''comportamiento indefinido'', que es básicamente suerte del sorteo, y nunca quieres que eso suceda.


Olvidando inicializar punteros, dejándolos con direcciones de memoria aleatorias. Nota: esto no siempre puede segfault, pero podría.

int* p1; //No initialization. *p1 = 3; //Possible segfault.


Una de mis favoritas:

#include <iostream> struct A { virtual void f() { std::cout << "A::f();/n"; } int i; }; struct B : A { virtual void f() { std::cout << "B::f();/n"; } int j; }; void seti(A* arr, size_t size) { for (size_t i = 0; i < size; ++i) arr[i].i = 0; } int main() { B b[10]; seti(b, 10); b[3].f(); }

Como con la mayoría de las cosas que pueden causar una segfault, esto también puede fallar. En ideone, por ejemplo, b[3].f() falla, pero b[2].f() funciona.


La falla de segmentación es causada por malos accesos a la memoria, solo si su sistema operativo tiene una MMU. De lo contrario, no lo obtendrás sino solo un comportamiento extraño.

La memoria virtual (toda la memoria a la que tiene acceso = 2 ^ sizeof(pointer type) ) se asigna a la memoria física en unidades llamadas páginas o segmentos (paginación segmentada pero aún se usan).

Cada página tiene algunos derechos de protección, si intenta leer desde una página sin acceso de lectura obtendrá una segfault. Si intenta escribir en una ubicación de solo lectura, obtendrá un SIGSEGV.

Si tiene un puntero unitario y lo usa, puede suceder que apunte a otra buena ubicación para que no obtenga un segfault. Si tiene una pequeña lectura de matriz después de que está encuadernada, puede dañar otras áreas de memoria si no pasa el límite de página.

Además, dado que hay muchas páginas, no todas están realmente mapeadas. Si tocas una página no mapeada obtendrás una segfault. En realidad, cualquier acceso a una página no mapeada tendrá que tener en cuenta la copia en escritura, las páginas en intercambio, la carga diferida, los archivos mapeados en memoria y otras cosas. Consulte este artículo sobre el manejo de fallas de página , especialmente el segundo diagrama allí, publicado aquí abajo también (pero lea el artículo para obtener más explicaciones)

Le interesa principalmente lo que sucede en el espacio de usuario y todas las rutas que conducen a SIGSEGV. pero el espacio del kernel también es interesante.