2009-10-20 4 views
3

Ceci est un mad-hack, mais j'essaie de provoquer délibérément une segfault à un point particulier dans l'exécution, donc valgrind va me donner une trace de la pile.Valgrind: cause délibérément segfault

S'il y a une meilleure façon de le faire, dites-le moi, mais je serais toujours curieux de savoir comment procéder délibérément à une erreur de segmentation, et pourquoi ma tentative n'a pas fonctionné.

Ceci est ma tentative avortée:

long* ptr = (long *)0xF0000000; 
ptr = 10; 

Je pensais que valgrind devrait au moins prendre ce en écriture invalide, même si ce n'est pas une violation de segmentation. Valgrind n'en dit rien.

Des idées pourquoi?

EDIT

Réponse acceptée, mais j'ai encore quelques mises voix pour toutes les suggestions d'une façon plus saine d'esprit pour obtenir une trace de la pile ...

+0

Connexes: https: // stackoverflow.com/q/18986351/694576 – alk

Répondre

6

Il vous manque un * comme dans *ptr = 10 ? Ce que vous avez ne compilera pas.

Si tel est le cas, cela ne causera évidemment pas de problème de segmentation puisque vous ne faites qu'affecter un numéro. Déréférencement pourrait.

En supposant nulle déréférencement sur vos résultats OS dans un segfault, ce qui suit devrait faire l'affaire:

inline void seg_fault(void) 
{ 
    volatile int *p = reinterpret_cast<volatile int*>(0); 
    *p = 0x1337D00D; 
} 
+0

Le * est directement à côté du type "long *" – Joel

+1

Sur la ligne suivante. – GManNickG

+1

Je n'ai pas encore décidé quelle forme je préfère - "long * ptr", "long * ptr", "long * ptr" – Joel

2

Êtes-vous sur x86? Si c'est le cas, il existe en fait un opcode dans la CPU qui signifie "invoquer n'importe quel débogueur". C'est l'opcode CC, ou plus communément appelé int 3. Meilleure façon de déclencher est avec l'assembleur en ligne:

inline void debugger_halt(void) 
{ 
#ifdef MSVC 
    __asm int 3; 
#elif defined(GCC) 
    asm("int 3"); 
#else 
#pragma error Well, you'll have to figure out how to do inline assembly 
       in your compiler 
#endif 
} 

MSVC soutient également __debugbreak() qui est une rupture matérielle dans le code non managé et un MSIL « pause » dans le code managé.

2

Ne serait-il pas préférable d'envoyer le signal SEGV (11) au processus pour forcer un vidage?

+0

Généralement, vous ne peut pas connaître le point exact pendant l'exécution (sur lequel vous voulez envoyer SIGSEGV) de l'extérieur du processus. –

+1

Le processus peut envoyer SIGSEGV à lui-même: 'kill (getpid(), SIGSEGV);' – mark4o

5

Désolé de mentionner l'évidence, mais pourquoi ne pas utiliser gdb avec un breakbpoint, puis utiliser backtrace?

(gdb) b somewhere 
(gdb) r 
(gdb) bt 
+0

C'est ce que je pensais, mais je ne suis pas assez expérimenté sur gdb pour savoir comment. :) – GManNickG

7

Appelez simplement abort(). Ce n'est pas une erreur de segmentation mais cela devrait générer un vidage de base.

3

Comme mentionné dans d'autres réponses, vous pouvez simplement appeler abort() si vous voulez terminer votre programme de manière anormale, ou kill(getpid(), SIGSEGV) s'il doit s'agir d'une erreur de segmentation. Cela générera un fichier core que vous pourrez utiliser avec gdb pour obtenir une trace ou un débogage de pile même si vous n'êtes pas en train de tourner sous valgrind. En utilisant un valgrind client request, valgrind vous permet également de vider une trace de pile avec votre propre message personnalisé, puis de poursuivre l'exécution. La requête client ne fait rien lorsque le programme ne s'exécute pas sous valgrind.

#include <valgrind/valgrind.h> 
... 
VALGRIND_PRINTF_BACKTRACE("Encountered the foobar problem, x=%d, y=%d\n", x, y); 
Questions connexes