c++ - Cómo generar automáticamente un stacktrace cuando mi programa falla




gcc crash stack-trace assert (24)

Linux

Si bien ya se ha sugerido el uso de backtrace () en execinfo.h para imprimir un seguimiento de pila y salir correctamente cuando se produce un fallo de segmentación, no veo ninguna mención de las complejidades necesarias para garantizar que el retroceso resultante apunta a la ubicación real de el fallo (al menos para algunas arquitecturas - x86 y ARM).

Las dos primeras entradas en la cadena de cuadros de pila cuando ingresas al controlador de señales contienen una dirección de retorno dentro del controlador de señales y una dentro de sigaction () en libc. El marco de la pila de la última función llamada antes de la señal (que es la ubicación de la falla) se pierde.

Código

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef __USE_GNU
#define __USE_GNU
#endif

#include <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ucontext.h>
#include <unistd.h>

/* This structure mirrors the one found in /usr/include/asm/ucontext.h */
typedef struct _sig_ucontext {
 unsigned long     uc_flags;
 struct ucontext   *uc_link;
 stack_t           uc_stack;
 struct sigcontext uc_mcontext;
 sigset_t          uc_sigmask;
} sig_ucontext_t;

void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext)
{
 void *             array[50];
 void *             caller_address;
 char **            messages;
 int                size, i;
 sig_ucontext_t *   uc;

 uc = (sig_ucontext_t *)ucontext;

 /* Get the address at the time the signal was raised */
#if defined(__i386__) // gcc specific
 caller_address = (void *) uc->uc_mcontext.eip; // EIP: x86 specific
#elif defined(__x86_64__) // gcc specific
 caller_address = (void *) uc->uc_mcontext.rip; // RIP: x86_64 specific
#else
#error Unsupported architecture. // TODO: Add support for other arch.
#endif

 fprintf(stderr, "signal %d (%s), address is %p from %p\n", 
  sig_num, strsignal(sig_num), info->si_addr, 
  (void *)caller_address);

 size = backtrace(array, 50);

 /* overwrite sigaction with caller's address */
 array[1] = caller_address;

 messages = backtrace_symbols(array, size);

 /* skip first stack frame (points here) */
 for (i = 1; i < size && messages != NULL; ++i)
 {
  fprintf(stderr, "[bt]: (%d) %s\n", i, messages[i]);
 }

 free(messages);

 exit(EXIT_FAILURE);
}

int crash()
{
 char * p = NULL;
 *p = 0;
 return 0;
}

int foo4()
{
 crash();
 return 0;
}

int foo3()
{
 foo4();
 return 0;
}

int foo2()
{
 foo3();
 return 0;
}

int foo1()
{
 foo2();
 return 0;
}

int main(int argc, char ** argv)
{
 struct sigaction sigact;

 sigact.sa_sigaction = crit_err_hdlr;
 sigact.sa_flags = SA_RESTART | SA_SIGINFO;

 if (sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL) != 0)
 {
  fprintf(stderr, "error setting signal handler for %d (%s)\n",
    SIGSEGV, strsignal(SIGSEGV));

  exit(EXIT_FAILURE);
 }

 foo1();

 exit(EXIT_SUCCESS);
}

Salida

signal 11 (Segmentation fault), address is (nil) from 0x8c50
[bt]: (1) ./test(crash+0x24) [0x8c50]
[bt]: (2) ./test(foo4+0x10) [0x8c70]
[bt]: (3) ./test(foo3+0x10) [0x8c8c]
[bt]: (4) ./test(foo2+0x10) [0x8ca8]
[bt]: (5) ./test(foo1+0x10) [0x8cc4]
[bt]: (6) ./test(main+0x74) [0x8d44]
[bt]: (7) /lib/libc.so.6(__libc_start_main+0xa8) [0x40032e44]

Todos los peligros de llamar a las funciones backtrace () en un manejador de señales aún existen y no deben pasarse por alto, pero me parece que la funcionalidad que describí aquí es muy útil para los errores de depuración.

Es importante tener en cuenta que el ejemplo que proporcioné está desarrollado / probado en Linux para x86. También lo he implementado con éxito en ARM usando uc_mcontext.arm_pc lugar de uc_mcontext.eip .

Aquí hay un enlace al artículo donde aprendí los detalles de esta implementación: http://www.linuxjournal.com/article/6391

Estoy trabajando en Linux con el compilador GCC. Cuando mi programa C ++ falla, me gustaría que generara automáticamente un seguimiento de pila.

Mi programa está siendo ejecutado por muchos usuarios diferentes y también se ejecuta en Linux, Windows y Macintosh (todas las versiones se compilan usando gcc ).

Me gustaría que mi programa pueda generar un seguimiento de la pila cuando se bloquee y la próxima vez que el usuario lo ejecute, les preguntará si está bien que me envíen el seguimiento de la pila para que pueda localizar el problema. Puedo manejar el envío de la información, pero no sé cómo generar la cadena de seguimiento. ¿Algunas ideas?


Puedo ayudar con la versión de Linux: se pueden usar las funciones backtrace, backtrace_symbols y backtrace_symbols_fd. Consulte las páginas de manual correspondientes.



He estado mirando este problema por un tiempo.

Y enterrado profundamente en las herramientas de rendimiento de Google README

http://code.google.com/p/google-perftools/source/browse/trunk/README

habla de libunwind

libunwind

Me encantaría escuchar las opiniones de esta biblioteca.

El problema con -rdynamic es que puede aumentar el tamaño del binario de manera relativamente significativa en algunos casos


Olvídese de cambiar sus fuentes y realice algunos trucos con la función backtrace () o macroses, estas son solo soluciones pobres.

Como una solución que funciona correctamente, aconsejaría:

  1. Compile su programa con el indicador "-g" para incrustar símbolos de depuración en binarios (no se preocupe, esto no afectará su rendimiento).
  2. En linux, ejecute el siguiente comando: "ulimit -c unlimited" - para permitir que el sistema realice grandes volcados.
  3. Cuando se bloqueó su programa, en el directorio de trabajo verá el archivo "core".
  4. Ejecute el siguiente comando para imprimir backtrace en stdout: gdb -batch -ex "backtrace" ./your_program_exe ./core

Esto imprimirá el seguimiento legible adecuado de su programa de forma legible para el ser humano (con nombres de archivos de origen y números de línea). Además, este enfoque le dará libertad para automatizar su sistema: tenga una secuencia de comandos corta que compruebe si el proceso creó un volcado de núcleo, y luego envíe los registros por correo electrónico a los desarrolladores, o inicie sesión en algún sistema de registro.


El nuevo rey de la ciudad ha llegado https://github.com/bombela/backward-cpp

1 encabezado para colocar en tu código y 1 biblioteca para instalar.

Personalmente lo llamo usando esta función.

#include "backward.hpp"
void stacker() {

using namespace backward;
StackTrace st;


st.load_here(99); //Limit the number of trace depth to 99
st.skip_n_firsts(3);//This will skip some backward internal function from the trace

Printer p;
p.snippet = true;
p.object = true;
p.color = true;
p.address = true;
p.print(st, stderr);
}

Puede usar DeathHandler , una clase pequeña de C ++ que hace todo por usted, confiable.


Aunque se ha proporcionado una respuesta correcta que describe cómo utilizar la función 1 de GNU libc backtrace() y proporcioné mi propia respuesta que describe cómo garantizar que un retroceso desde un controlador de señales apunta a la ubicación real del error 2 , no No vea ninguna mención de la salida de símbolos de C ++ demangling desde el backtrace.

Al obtener backtraces de un programa de C ++, la salida se puede ejecutar a través de c++filt 1 para desentrañar los símbolos o usando abi::__cxa_demangle 1 directamente.

  • 1 Linux y OS X Tenga en cuenta que c++filt y __cxa_demangle son específicos de GCC
  • 2 Linux

El siguiente ejemplo de C ++ Linux usa el mismo controlador de señal que mi otra respuesta y demuestra cómo se puede usar c++filt para desentrañar los símbolos.

Código :

class foo
{
public:
    foo() { foo1(); }

private:
    void foo1() { foo2(); }
    void foo2() { foo3(); }
    void foo3() { foo4(); }
    void foo4() { crash(); }
    void crash() { char * p = NULL; *p = 0; }
};

int main(int argc, char ** argv)
{
    // Setup signal handler for SIGSEGV
    ...

    foo * f = new foo();
    return 0;
}

Salida ( ./test ):

signal 11 (Segmentation fault), address is (nil) from 0x8048e07
[bt]: (1) ./test(crash__3foo+0x13) [0x8048e07]
[bt]: (2) ./test(foo4__3foo+0x12) [0x8048dee]
[bt]: (3) ./test(foo3__3foo+0x12) [0x8048dd6]
[bt]: (4) ./test(foo2__3foo+0x12) [0x8048dbe]
[bt]: (5) ./test(foo1__3foo+0x12) [0x8048da6]
[bt]: (6) ./test(__3foo+0x12) [0x8048d8e]
[bt]: (7) ./test(main+0xe0) [0x8048d18]
[bt]: (8) ./test(__libc_start_main+0x95) [0x42017589]
[bt]: (9) ./test(__register_frame_info+0x3d) [0x8048981]

Salida demangled ( ./test 2>&1 | c++filt ):

signal 11 (Segmentation fault), address is (nil) from 0x8048e07
[bt]: (1) ./test(foo::crash(void)+0x13) [0x8048e07]
[bt]: (2) ./test(foo::foo4(void)+0x12) [0x8048dee]
[bt]: (3) ./test(foo::foo3(void)+0x12) [0x8048dd6]
[bt]: (4) ./test(foo::foo2(void)+0x12) [0x8048dbe]
[bt]: (5) ./test(foo::foo1(void)+0x12) [0x8048da6]
[bt]: (6) ./test(foo::foo(void)+0x12) [0x8048d8e]
[bt]: (7) ./test(main+0xe0) [0x8048d18]
[bt]: (8) ./test(__libc_start_main+0x95) [0x42017589]
[bt]: (9) ./test(__register_frame_info+0x3d) [0x8048981]

Lo siguiente se basa en el controlador de señales de mi respuesta original y puede reemplazar el controlador de señales en el ejemplo anterior para demostrar cómo abi::__cxa_demangle se puede usar para desentrañar los símbolos. Este manejador de señales produce la misma salida descompuesta que el ejemplo anterior.

Código :

void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext)
{
    sig_ucontext_t * uc = (sig_ucontext_t *)ucontext;

    void * caller_address = (void *) uc->uc_mcontext.eip; // x86 specific

    std::cerr << "signal " << sig_num 
              << " (" << strsignal(sig_num) << "), address is " 
              << info->si_addr << " from " << caller_address 
              << std::endl << std::endl;

    void * array[50];
    int size = backtrace(array, 50);

    array[1] = caller_address;

    char ** messages = backtrace_symbols(array, size);    

    // skip first stack frame (points here)
    for (int i = 1; i < size && messages != NULL; ++i)
    {
        char *mangled_name = 0, *offset_begin = 0, *offset_end = 0;

        // find parantheses and +address offset surrounding mangled name
        for (char *p = messages[i]; *p; ++p)
        {
            if (*p == '(') 
            {
                mangled_name = p; 
            }
            else if (*p == '+') 
            {
                offset_begin = p;
            }
            else if (*p == ')')
            {
                offset_end = p;
                break;
            }
        }

        // if the line could be processed, attempt to demangle the symbol
        if (mangled_name && offset_begin && offset_end && 
            mangled_name < offset_begin)
        {
            *mangled_name++ = '\0';
            *offset_begin++ = '\0';
            *offset_end++ = '\0';

            int status;
            char * real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);

            // if demangling is successful, output the demangled function name
            if (status == 0)
            {    
                std::cerr << "[bt]: (" << i << ") " << messages[i] << " : " 
                          << real_name << "+" << offset_begin << offset_end 
                          << std::endl;

            }
            // otherwise, output the mangled function name
            else
            {
                std::cerr << "[bt]: (" << i << ") " << messages[i] << " : " 
                          << mangled_name << "+" << offset_begin << offset_end 
                          << std::endl;
            }
            free(real_name);
        }
        // otherwise, print the whole line
        else
        {
            std::cerr << "[bt]: (" << i << ") " << messages[i] << std::endl;
        }
    }
    std::cerr << std::endl;

    free(messages);

    exit(EXIT_FAILURE);
}

Utilizaría el código que genera un seguimiento de pila para la memoria filtrada en el Detector de fugas visual . Sin embargo, esto solo funciona en Win32.


No especificó su sistema operativo, por lo que es difícil de responder. Si está utilizando un sistema basado en gnu libc, es posible que pueda usar la función libc backtrace() .

GCC también tiene dos componentes integrados que pueden ayudarlo, pero que pueden o no implementarse completamente en su arquitectura, y son __builtin_frame_address y __builtin_return_address . Ambos quieren un nivel entero inmediato (por inmediato, quiero decir que no puede ser una variable). Si __builtin_frame_address para un nivel dado no es cero, debería ser seguro tomar la dirección de retorno del mismo nivel.


Consulte la función Stack Trace en ACE (ADAPTIVE Communication Environment). Ya está escrito para cubrir todas las plataformas principales (y más). La biblioteca tiene una licencia de estilo BSD, por lo que incluso puede copiar / pegar el código si no desea utilizar ACE.


Gracias a enthusiasticgeek por llamar mi atención a la utilidad addr2line.

He escrito una secuencia de comandos rápida y sucia para procesar la salida de la respuesta que se proporciona here : (¡gracias a jschmier!) Mediante la utilidad addr2line.

La secuencia de comandos acepta un solo argumento: el nombre del archivo que contiene la salida de la utilidad de jschmier.

La salida debe imprimir algo como lo siguiente para cada nivel de la traza:

BACKTRACE:  testExe 0x8A5db6b
FILE:       pathToFile/testExe.C:110
FUNCTION:   testFunction(int) 
   107  
   108           
   109           int* i = 0x0;
  *110           *i = 5;
   111      
   112        }
   113        return i;

Código:

#!/bin/bash

LOGFILE=$1

NUM_SRC_CONTEXT_LINES=3

old_IFS=$IFS  # save the field separator           
IFS=$'\n'     # new field separator, the end of line           

for bt in `cat $LOGFILE | grep '\[bt\]'`; do
   IFS=$old_IFS     # restore default field separator 
   printf '\n'
   EXEC=`echo $bt | cut -d' ' -f3 | cut -d'(' -f1`  
   ADDR=`echo $bt | cut -d'[' -f3 | cut -d']' -f1`
   echo "BACKTRACE:  $EXEC $ADDR"
   A2L=`addr2line -a $ADDR -e $EXEC -pfC`
   #echo "A2L:        $A2L"

   FUNCTION=`echo $A2L | sed 's/\<at\>.*//' | cut -d' ' -f2-99`
   FILE_AND_LINE=`echo $A2L | sed 's/.* at //'`
   echo "FILE:       $FILE_AND_LINE"
   echo "FUNCTION:   $FUNCTION"

   # print offending source code
   SRCFILE=`echo $FILE_AND_LINE | cut -d':' -f1`
   LINENUM=`echo $FILE_AND_LINE | cut -d':' -f2`
   if ([ -f $SRCFILE ]); then
      cat -n $SRCFILE | grep -C $NUM_SRC_CONTEXT_LINES "^ *$LINENUM\>" | sed "s/ $LINENUM/*$LINENUM/"
   else
      echo "File not found: $SRCFILE"
   fi
   IFS=$'\n'     # new field separator, the end of line           
done

IFS=$old_IFS     # restore default field separator 

Olvidé la tecnología de GNOME de "apport", pero no sé mucho sobre su uso. Se utiliza para generar stacktraces y otros diagnósticos para el procesamiento y puede archivar errores automáticamente. Sin duda vale la pena registrarse.


Puede que valga la pena ver Google Breakpad , un generador de volcado de fallos multiplataforma y herramientas para procesar los volcados.


Además de las respuestas anteriores, aquí se explica cómo hacer que el sistema operativo Debian Linux genere un volcado de memoria

  1. Cree una carpeta "coredumps" en la carpeta de inicio del usuario
  2. Vaya a /etc/security/limits.conf. Debajo de la línea '', escriba "soft core unlimited", y "root soft core unlimited" si habilita volcados de núcleo para root, para permitir espacio ilimitado para volcados de núcleo.
  3. NOTA: “* soft core unlimited” no cubre la raíz, por lo que la raíz debe especificarse en su propia línea.
  4. Para verificar estos valores, cierre sesión, vuelva a iniciar sesión y escriba "ulimit -a". El "tamaño del archivo del núcleo" se debe establecer en ilimitado.
  5. Verifique los archivos .bashrc (usuario y root si corresponde) para asegurarse de que ulimit no esté configurado allí. De lo contrario, el valor anterior se sobrescribirá en el inicio.
  6. Abra el archivo /etc/sysctl.conf. Introduzca lo siguiente en la parte inferior: "kernel.core_pattern = /home//coredumps/%e_%t.dump". (% e será el nombre del proceso y% t será la hora del sistema)
  7. Salga y escriba "sysctl -p" para cargar la nueva configuración Verifique / proc / sys / kernel / core_pattern y verifique que esto coincida con lo que acaba de escribir.
  8. El volcado de núcleo se puede probar ejecutando un proceso en la línea de comando ("&"), y luego matándolo con "kill -11". Si el volcado de núcleo es exitoso, verá "(volcado de núcleo)" después de la indicación de falla de segmentación.

* nix: puede interceptar SIGSEGV (por lo general, esta señal se genera antes de fallar) y mantener la información en un archivo. (además del archivo central que puede usar para depurar usando gdb por ejemplo).

ganar: compruebe this desde msdn.

También puede consultar el código chrome de google para ver cómo maneja los bloqueos. Tiene un bonito mecanismo de manejo de excepciones.


He visto muchas respuestas aquí realizando un manejador de señal y luego saliendo. Ese es el camino a seguir, pero recuerde un hecho muy importante: si desea obtener el volcado central para el error generado, no puede llamar a exit(status) . Llama abort() lugar!


Es incluso más fácil que "man backtrace", hay una biblioteca poco documentada (específica de GNU) distribuida con glibc como libSegFault.so, que creo que fue escrita por Ulrich Drepper para respaldar el programa catchsegv (ver "man catchsegv").

Esto nos da 3 posibilidades. En lugar de ejecutar "programa -o hai":

  1. Ejecutar dentro de catchsegv:

    $ catchsegv program -o hai
    
  2. Enlace con libSegFault en tiempo de ejecución:

    $ LD_PRELOAD=/lib/libSegFault.so program -o hai
    
  3. Enlace con libSegFault en tiempo de compilación:

    $ gcc -g1 -lSegFault -o program program.cc
    $ program -o hai
    

En los 3 casos, obtendrá backtraces más claros con menos optimización (gcc -O0 o -O1) y símbolos de depuración (gcc -g). De lo contrario, puede terminar con un montón de direcciones de memoria.

También puedes capturar más señales para trazas de pila con algo como:

$ export SEGFAULT_SIGNALS="all"       # "all" signals
$ export SEGFAULT_SIGNALS="bus abrt"  # SIGBUS and SIGABRT

La salida tendrá un aspecto similar a este (observe el retroceso en la parte inferior):

*** Segmentation fault Register dump:

 EAX: 0000000c   EBX: 00000080   ECX:
00000000   EDX: 0000000c  ESI:
bfdbf080   EDI: 080497e0   EBP:
bfdbee38   ESP: bfdbee20

 EIP: 0805640f   EFLAGS: 00010282

 CS: 0073   DS: 007b   ES: 007b   FS:
0000   GS: 0033   SS: 007b

 Trap: 0000000e   Error: 00000004  
OldMask: 00000000  ESP/signal:
bfdbee20   CR2: 00000024

 FPUCW: ffff037f   FPUSW: ffff0000  
TAG: ffffffff  IPOFF: 00000000  
CSSEL: 0000   DATAOFF: 00000000  
DATASEL: 0000

 ST(0) 0000 0000000000000000   ST(1)
0000 0000000000000000  ST(2) 0000
0000000000000000   ST(3) 0000
0000000000000000  ST(4) 0000
0000000000000000   ST(5) 0000
0000000000000000  ST(6) 0000
0000000000000000   ST(7) 0000
0000000000000000

Backtrace:
/lib/libSegFault.so[0xb7f9e100]
??:0(??)[0xb7fa3400]
/usr/include/c++/4.3/bits/stl_queue.h:226(_ZNSt5queueISsSt5dequeISsSaISsEEE4pushERKSs)[0x805647a]
/home/dbingham/src/middle-earth-mud/alpha6/src/engine/player.cpp:73(_ZN6Player5inputESs)[0x805377c]
/home/dbingham/src/middle-earth-mud/alpha6/src/engine/socket.cpp:159(_ZN6Socket4ReadEv)[0x8050698]
/home/dbingham/src/middle-earth-mud/alpha6/src/engine/socket.cpp:413(_ZN12ServerSocket4ReadEv)[0x80507ad]
/home/dbingham/src/middle-earth-mud/alpha6/src/engine/socket.cpp:300(_ZN12ServerSocket4pollEv)[0x8050b44]
/home/dbingham/src/middle-earth-mud/alpha6/src/engine/main.cpp:34(main)[0x8049a72]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0xb7d1b775]
/build/buildd/glibc-2.9/csu/../sysdeps/i386/elf/start.S:122(_start)[0x8049801]

Si desea conocer los detalles sangrientos, desafortunadamente, la mejor fuente es la fuente: consulte http://sourceware.org/git/?p=glibc.git;a=blob;f=debug/segfault.c y su directorio principal http://sourceware.org/git/?p=glibc.git;a=tree;f=debug


Como solución solo para Windows, puede obtener el equivalente a un seguimiento de pila (con mucha, mucha más información) utilizando WER . Con solo unas pocas entradas de registro, se puede configurar para recopilar volcados en modo usuario :

A partir de Windows Server 2008 y Windows Vista con Service Pack 1 (SP1), el Informe de errores de Windows (WER) se puede configurar para que los volcados de modo de usuario completos se recopilen y almacenen localmente después de que una aplicación de modo de usuario falla. [...]

Esta característica no está habilitada por defecto. Habilitar la característica requiere privilegios de administrador. Para habilitar y configurar la función, use los siguientes valores de registro en la clave HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ Windows \ Windows \ Windows \ ReportDault

Puede configurar las entradas de registro desde su instalador, que tiene los privilegios necesarios.

La creación de un volcado en modo de usuario tiene las siguientes ventajas sobre la generación de un seguimiento de pila en el cliente:

  • Ya está implementado en el sistema. Puede usar WER como se describe anteriormente, o llamar a MiniDumpWriteDump usted mismo, si necesita un control más preciso sobre la cantidad de información a volcar. (Asegúrese de llamarlo desde un proceso diferente.)
  • Mucho más completo que una traza de pila. Entre otros, puede contener variables locales, argumentos de funciones, pilas para otros subprocesos, módulos cargados, etc. La cantidad de datos (y, por consiguiente, el tamaño) es altamente personalizable.
  • No hay necesidad de enviar símbolos de depuración. Esto reduce drásticamente el tamaño de su implementación, y también hace que sea más difícil aplicar ingeniería inversa a su aplicación.
  • En gran parte independiente del compilador que utiliza. El uso de WER ni siquiera requiere ningún código. De cualquier manera, tener una forma de obtener una base de datos de símbolos (PDB) es muy útil para el análisis fuera de línea. Creo que GCC puede generar PDB, o existen herramientas para convertir la base de datos de símbolos al formato PDB.

Tenga en cuenta que WER solo puede ser activado por un bloqueo de la aplicación (es decir, el sistema termina un proceso debido a una excepción no controlada) MiniDumpWriteDumpSe puede llamar en cualquier momento. Esto puede ser útil si necesita volcar el estado actual para diagnosticar problemas que no sean una falla.

Lectura obligatoria, si desea evaluar la aplicabilidad de mini dumps:



En Linux / Unix / MacOSX, use los archivos principales (puede habilitarlos con ulimit o llamada al sistema compatible ). En Windows, utilice los informes de errores de Microsoft (puede convertirse en socio y obtener acceso a los datos de bloqueo de su aplicación).


Mirar:

hombre 3 retroceso

Y:

#include <exeinfo.h>
int backtrace(void **buffer, int size);

Estas son las extensiones de GNU.


ulimit -c unlimited

es una variable del sistema, que permitirá crear un volcado de memoria después de que la aplicación se bloquee. En este caso una cantidad ilimitada. Busque un archivo llamado núcleo en el mismo directorio. ¡Asegúrese de compilar su código con las informaciones de depuración habilitadas!

Saludos


Para idiomas que no especifican un modelo de memoria, está escribiendo código para el idioma y el modelo de memoria especificado por la arquitectura del procesador. El procesador puede optar por reordenar los accesos de memoria para el rendimiento. Por lo tanto, si su programa tiene carreras de datos (una carrera de datos es cuando es posible que múltiples núcleos / hipercrocesos accedan a la misma memoria simultáneamente), entonces su programa no es multiplataforma debido a su dependencia del modelo de memoria del procesador. Puede consultar los manuales del software Intel o AMD para averiguar cómo los procesadores pueden reordenar los accesos a la memoria.

Muy importante, los bloqueos (y la semántica de concurrencia con el bloqueo) se implementan normalmente de forma multiplataforma ... Entonces, si está utilizando bloqueos estándar en un programa multiproceso sin carreras de datos, entonces no tiene que preocuparse por los modelos de memoria multiplataforma .

Curiosamente, los compiladores de Microsoft para C ++ tienen semántica de adquisición / lanzamiento para volatile, que es una extensión de C ++ para hacer frente a la falta de un modelo de memoria en C ++ http://msdn.microsoft.com/en-us/library/12a04hfd(v=vs.80).aspx . Sin embargo, dado que Windows solo se ejecuta en x86 / x64, eso no significa mucho (los modelos de memoria de Intel y AMD hacen que sea fácil y eficiente implementar semántica de adquisición / lanzamiento en un idioma).





c++ gcc crash stack-trace assert