2010-01-11 29 views
17

OK, por la razón que sea, tengo problemas para causar un error de seg. Quiero producir uno para poder usar gdb para ver cómo depurar uno. He probado ambos ejemplos del artículo the Wikipedia y tampoco funcionan.¿Por qué no puedo causar un error seg?

La primera de ellas:

char *s = "Hello World!"; 
*s = 'H'; 

Y el segundo ejemplo:

int main(void) 
{ 
    main(); 
} 

EDIT: estoy usando Ubutnu 9.10 y g++ como mi compilador. ¿Alguien puede mostrarme algún código que garantice segfault?

+2

El comportamiento del código anterior es indefinido, lo que significa que puede hacer cualquier cosa que quiere, incluso "parece que funciona", o causa demonios nasales. :-) –

+1

try char * = reinterpret_cast (0x1234); p [0] = 'H'; –

+13

Si quieres causar una falla seg, lo que podría enviar a algunos de los programas de C++ que escribí en la universidad :-) – ristonj

Respuesta

37

Se impossable para tratar de hacerlo fiable eliminación de referencias punteros.
Esto se debe a cómo maneja la aplicación de memoria puede variar de compilador compilador también a través del mismo compilador con otras opciones (modo debug/release handeled diferente).

Lo que puede hacer es plantear explícitamente la violación de segmento utilizando una señal:

#include <signal.h> 

int main() 
{ 
    raise(SIGSEGV); 
} 
+0

Es incorrecto afirmar que "es imposible de probar y confiable hacerlo desmarcando punteros". - puede utilizar pruebas y análisis de su código para establecer que segfaults confiablemente. – user1976

+0

@ user1976: Aparentemente no entiendes lo que significa un comportamiento indefinido. –

+0

@ Loki Astari: Un comportamiento indefinido significa que los compiladores (muy) recientes (clang siendo el peor delincuente) se sienten libres de ser molestos y eliminan su código. Sin embargo, eso no significa que no se pueda confiar en que el código generado muestre un comportamiento bien definido. Simplemente necesita confiar en otro método, fuera del estándar C++, para garantizar esto. – user1976

1
char * ptr = 0; 
*ptr = 1; 

Segmentation fault 
2
int *hello = NULL; 
printf(*hello); 

o puede definir una estructura (digamos estructura HelloWorld)

HelloWorld *myWorld = NULL; 
myWorld->world = "hello"; 
5

Tanto de las cosas que haces va a producir "un comportamiento indefinido" en C++ (bueno, llamando main() es realmente explícitamente prohibido). No hay garantía de que causen fallas seg. Esto dependerá de muchas cosas, pero principalmente de la plataforma en la que se está ejecutando, que no ha especificado.

De hecho, cualquier método sugerido para causar un fallo de seg puede o no funcionar. Esto se debe a que una falla de segmentación casi siempre está asociada con el concepto de comportamiento indefinido de C++.

+4

Es un comportamiento indefinido desde el punto de vista del lenguaje, pero el sistema operativo probablemente defina las condiciones bajo las cuales ocurre una falla de segmentación, y puede forzar esa condición en C++. (Ejemplo: 'int * p = 0; while (true) * p ++ = 10;' golpeará en un punto u otro un segmento de memoria que no puede ser grabado por el proceso, y bajo linux o macosx activará un error de segmentación) –

2

Muchas formas de generar una segfault.

Al igual que una mala eliminación de referencias de puntero:

char *s = (char *)0xDEADBEEF; 
*s = 'a'; 
+0

'0xDEADBEEF' es un número. "Hello World" es una cadena. En este caso, 's' termina apuntando a la dirección de memoria' 0xDEADBEEF', que es (muy probablemente) completamente inválida. En el ejemplo de OP, 's' termina conteniendo la dirección de la cadena; si el compilador no ha declarado la memoria como de solo lectura, no se generarán errores si intentamos escribir en ella. –

+1

Pruebe 0xBADBADBAD - realmente, realmente, realmente malo – user1976

16

Mi sabor una línea:

*(char *)0 = 0; 
+3

Incluso eso no garantiza la segfault. Es solo un comportamiento indefinido. Que puede o no funcionar –

+2

@Martin - garantizado en todas las plataformas, no. Esto causará una segfault en Ubuntu Linux, sí. –

+0

@R: ¡No se puede garantizar eso! ¿Por qué crees que Ubunt es tan especial? Confiar en un comportamiento indefinido para hacer algo especial es simplemente pedir que se queme bastante mal en algún momento del camino. Se describe como no definido por una razón. Simplemente no lo hagas a menos que explícitamente sepas lo que sucederá y no lo hagas –

1

El artículo de Wikipedia realidad enumera tres métodos (uno de los cuales es una referencia a un puntero nulo); ¿Por qué no trataste eso?

En cuanto a por qué los dos ejemplos que probó no, bueno, la respuesta correcta como otros han notado es que es un comportamiento indefinido, por lo que cualquier cosa podría suceder (lo que incluye no segfaulting). Pero uno podría especular que la razón por la cual el primer formulario no falló para usted es porque su compilador o sistema es poco estricto con respecto a la protección de la memoria. En cuanto al segundo caso, un compilador de recursividad de cola podría concebiblemente optimizar el bucle infinitamente recursivo main y no terminar desbordando la pila.

2

Para el primer ejemplo, el compilador probablemente puso la cadena en la memoria grabable, por lo que no hay un fallo seg cuando intenta cambiarlo.

Por el momento, el compilador puede optimizar la llamada o optimizar la llamada en solo un salto (ya que es tail call), lo que significa que la pila no está creciendo con direcciones de retorno para cada llamada , por lo que podría recurse indefinidamente.

Pero como mencionó Neil en su publicación, cualquiera de estas cosas resulta en un "comportamiento indefinido", por lo que el código no es necesario en el tiempo de ejecución para generar un error seg.

1

Si intentas concatenar dos constantes ... obtendrás una ...al menos es una forma sencilla ...

strcat ("a", "b");

=)

+1

solo si los literales están asignados en la memoria de solo lectura. Lo que aparentemente no es en su caso, o su manipulación de cadena habría causado una segfault en primer lugar. – jalf

+0

En realidad, strcat ("seg", "fault"); está garantizado para producir un segfault. – user1976

5

violación de segmento más corto jamás:

*(int*)0=0; 
+29

mucho más corto: '* (short *) 0 = 0' lol – smerlin

+1

@smerlin: +1 por humor sutil. –

Cuestiones relacionadas