Je voudrais forcer un vidage de mémoire à un emplacement spécifique dans mon application C++.
Je sais que je peux le faire en faisant quelque chose comme:
int * crash = NULL;
*crash = 1;
Mais je voudrais savoir s'il existe une méthode plus propre?
J'utilise Linux d'ailleurs.
L'élévation du signal numéro 6 (SIGABRT
sous Linux) est une façon de le faire (mais gardez à l'esprit que SIGABRT n'est pas requis pour être 6 dans toutes les implémentations POSIX, vous pouvez donc utiliser la valeur SIGABRT
elle-même si c'est autre chose que du code de débogage quick'n'dirty).
#include <signal.h>
: : :
raise (SIGABRT);
L'appel de abort()
provoquera également un vidage de mémoire, et vous pouvez même le faire sans terminer votre processus en appelant fork()
suivi de abort()
chez l'enfant uniquement - voir cette réponse pour plus de détails.
Il y a quelques années, Google a publié la bibliothèque coredumper .
Présentation
La bibliothèque coredumper peut être compilée en applications pour créer des vidages de mémoire du programme en cours d'exécution - sans se terminer. Il prend en charge les vidages de mémoire à thread unique et à threads multiples, même si le noyau ne prend pas en charge nativement les fichiers core à threads multiples.
Coredumper est distribué selon les termes de la licence BSD.
Exemple
Ce n'est en aucun cas un exemple complet; il vous donne simplement une idée de l'apparence de l'API coredumper.
#include <google/coredumper.h> ... WriteCoreDump('core.myprogram'); /* Keep going, we generated a core file, * but we didn't crash. */
Ce n'est pas ce que vous demandiez, mais c'est peut-être encore mieux :)
Comme indiqué dans la page de manuel du signal , tout signal avec l'action répertoriée comme 'core' forcera un vidage de mémoire. Certains exemples sont:
SIGQUIT 3 Core Quit from keyboard
SIGILL 4 Core Illegal Instruction
SIGABRT 6 Core Abort signal from abort(3)
SIGFPE 8 Core Floating point exception
SIGSEGV 11 Core Invalid memory reference
Assurez-vous d'activer les vidages mémoire:
ulimit -c unlimited
#include <stdlib.h> // C
//#include <cstdlib> // C++
void core_dump(void)
{
abort();
}
avorter();
Associé, parfois vous souhaitez une trace arrière sans vidage de mémoire réel et permettre au programme de continuer à fonctionner: consultez les fonctions glibc backtrace () et backtrace_symbols (): http://www.gnu.org/ s/libc/manual/html_node/Backtraces.html
Une autre façon de générer un vidage de mémoire:
$ bash
$ kill -s SIGSEGV $$
Créez simplement une nouvelle instance de bash et tuez-la avec le signal spécifié. Le $$
est le PID du Shell. Sinon, vous tuez votre bash actuel et serez déconnecté, terminal fermé ou déconnecté.
$ bash
$ kill -s SIGABRT $$
$ bash
$ kill -s SIGFPE $$
Vous pouvez utiliser kill (2) pour envoyer un signal.
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
Alors,
kill(getpid(), SIGSEGV);
Parfois, il peut être approprié de faire ce qui suit:
int st = 0;
pid_t p = fork();
if (!p) {
signal(SIGABRT, SIG_DFL);
abort(); // having the coredump of the exact copy of the calling thread
} else {
waitpid(p, &st, 0); // rip the zombie
}
// here the original process continues to live
Un problème avec cette approche simple est qu'un seul thread sera coredumpé.
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("\n");
printf("Process is aborting\n");
abort();
printf("Control not reaching here\n");
return 0;
}
utilisez cette approche où vous voulez :)
#include <assert.h>
.
.
.
assert(!"this should not happen");