243 votes

Comment générer un core dump dans Linux lors d'une segmentation fault ?

J'ai un processus sous Linux qui provoque une erreur de segmentation. Comment puis-je lui dire de générer un vidage de cœur lorsqu'il échoue ?

1 votes

Comment le consulter par la suite : stackoverflow.com/questions/8305866/…

271voto

Eli Courtwright Points 53071

Cela dépend de quel shell vous utilisez. Si vous utilisez bash, alors la commande ulimit contrôle plusieurs paramètres liés à l'exécution du programme, comme la possibilité de générer un core dump. Si vous tapez

ulimit -c unlimited

cela indiquera à bash que ses programmes peuvent générer des cores de n'importe quelle taille. Vous pouvez spécifier une taille comme 52M au lieu de illimité si vous le souhaitez, mais en pratique cela ne devrait pas être nécessaire puisque la taille des fichiers core ne sera probablement jamais un problème pour vous.

Dans tcsh, vous devriez taper

limit coredumpsize unlimited

0 votes

Je suis désolé, mais cela répond-il vraiment à votre question? Vous avez demandé comment générer, mais cela dit comment définir les limites.

25 votes

@lzprgmr : Pour clarifier : la raison pour laquelle les cœurs ne sont pas générés par défaut est que la limite n'est pas définie et/ou définie à 0, ce qui empêche le cœur d'être vidé. En fixant une limite d'illimité, nous garantissons que les cœurs peuvent toujours être générés.

6 votes

Ce lien va plus loin et donne quelques options supplémentaires pour activer la génération de dumps de cœur sous Linux. Le seul inconvénient est que certaines commandes/réglages ne sont pas expliqués.

68voto

George Colpitts Points 131

Telle que expliquée ci-dessus, la vraie question posée ici est de savoir comment activer les vidages de la mémoire principale (core dumps) sur un système où ils ne sont pas activés. Cette question est répondue ici.

Si vous êtes venu ici en espérant apprendre comment générer un vidage de la mémoire principale pour un processus bloqué, la réponse est

gcore 

si gcore n'est pas disponible sur votre système alors

kill -ABRT 

Ne pas utiliser kill -SEGV car cela invoque souvent un gestionnaire de signaux rendant plus difficile le diagnostic du processus bloqué

2 votes

Je pense qu'il est beaucoup plus probable que -ABRT invoque un gestionnaire de signaux que -SEGV, car une interruption est plus susceptible d'être récupérable qu'une erreur de segmentation. (Si vous gérez une erreur de segmentation, normalement elle se déclenchera à nouveau dès que votre gestionnaire aura quitté.) Un meilleur choix de signal pour générer un vidage de cœur est -QUIT.

30voto

Nathan Fellman Points 31310

Ce que j'ai fait à la fin était d'attacher gdb au processus avant qu'il ne plante, et ensuite quand il a obtenu la segmentation-fault, j'ai exécuté la commande generate-core-file. Cela a forcé la génération d'un fichier de vidage mémoire.

0 votes

Comment avez-vous attaché gdb au processus ?

7 votes

Pour répondre à Ritwik G, pour attacher un processus à gdb, il suffit de lancer gdb et d'entrer 'attach ' où est le numéro pid du processus que vous souhaitez attacher.

0 votes

(abrégé en ge)

19voto

t0mm13b Points 21031

Peut-être pourriez-vous le faire de cette façon, ce programme est une démonstration de la manière de piéger une erreur de segmentation et d'appeler un débogueur (c'est le code original utilisé sous AIX) et affiche la trace de la pile jusqu'au point de l'erreur de segmentation. Vous devrez modifier la variable sprintf pour utiliser gdb dans le cas de Linux.

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>

static void signal_handler(int);
static void dumpstack(void);
static void cleanup(void);
void init_signals(void);
void panic(const char *, ...);

struct sigaction sigact;
char *progname;

int main(int argc, char **argv) {
    char *s;
    progname = *(argv);
    atexit(cleanup);
    init_signals();
    printf("About to seg fault by assigning zero to *s\n");
    *s = 0;
    sigemptyset(&sigact.sa_mask);
    return 0;
}

void init_signals(void) {
    sigact.sa_handler = signal_handler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigaction(SIGINT, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGSEGV);
    sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGBUS);
    sigaction(SIGBUS, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGQUIT);
    sigaction(SIGQUIT, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGHUP);
    sigaction(SIGHUP, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGKILL);
    sigaction(SIGKILL, &sigact, (struct sigaction *)NULL);
}

static void signal_handler(int sig) {
    if (sig == SIGHUP) panic("FATAL: Program hanged up\n");
    if (sig == SIGSEGV || sig == SIGBUS){
        dumpstack();
        panic("FATAL: %s Fault. Logged StackTrace\n", (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown"));
    }
    if (sig == SIGQUIT) panic("QUIT signal ended program\n");
    if (sig == SIGKILL) panic("KILL signal ended program\n");
    if (sig == SIGINT) ;
}

void panic(const char *fmt, ...) {
    char buf[50];
    va_list argptr;
    va_start(argptr, fmt);
    vsprintf(buf, fmt, argptr);
    va_end(argptr);
    fprintf(stderr, buf);
    exit(-1);
}

static void dumpstack(void) {
    /* Got this routine from http://www.whitefang.com/unix/faq_toc.html
    ** Section 6.5. Modified to redirect to file to prevent clutter
    */
    /* This needs to be changed... */
    char dbx[160];

    sprintf(dbx, "echo 'where\ndetach' | dbx -a %d > %s.dump", getpid(), progname);
    /* Change the dbx to gdb */

    system(dbx);
    return;
}

void cleanup(void) {
    sigemptyset(&sigact.sa_mask);
    /* Do any cleaning up chores here */
}

Vous devrez peut-être ajouter un paramètre pour forcer gdb à générer le core comme indiqué dans ce blog ici.

17voto

mlutescu Points 71

Il y a plus de choses qui peuvent influencer la génération d'un vidage de la mémoire. J'ai rencontré ceux-ci :

  • le répertoire pour le vidage doit être accessible en écriture. Par défaut, c'est le répertoire courant du processus, mais cela peut être modifié en définissant /proc/sys/kernel/core_pattern.
  • dans certaines conditions, la valeur du noyau dans /proc/sys/fs/suid_dumpable peut empêcher la génération du vidage de la mémoire.

Il y a d'autres situations qui peuvent empêcher la génération et qui sont décrites dans la page de manuel - essayez man core.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X