Frage

Welche Methoden gibt es, automatisch einen stack-trace auf Unix-Systemen?Ich meine nicht einfach nur eine core-Datei anfügen und interaktiv mit GDB, aber mit einem SIGSEGV handler, dumps eine Ablaufverfolgung, um eine text-Datei.

Bonus-Punkte für die folgenden optionalen Funktionen:

  • Zusätzliche Informationen sammeln bei crash-Zeit (zB.config-Dateien).
  • E-Mail-crash-info-Paket an die Entwickler.
  • Fähigkeit zu fügen Sie diese in eine dlopened shared library
  • Nicht erfordern eine GUI
War es hilfreich?

Lösung

Wenn Sie sind auf Systemen mit dem BSD backtrace Funktionalität zur Verfügung (Linux, OSX 1.5 BSD-Kurs), können Sie dies programmatisch tun in Ihrer signal-handler.

Zum Beispiel (backtrace code abgeleitet von IBM-Beispiel):

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

void sig_handler(int sig)
{
    void * array[25];
    int nSize = backtrace(array, 25);
    char ** symbols = backtrace_symbols(array, nSize);

    for (int i = 0; i < nSize; i++)
    {
        puts(symbols[i]);;
    }

    free(symbols);

    signal(sig, &sig_handler);
}

void h()
{
    kill(0, SIGSEGV);
}

void g()
{
    h();
}

void f()
{
    g();
}

int main(int argc, char ** argv)
{
    signal(SIGSEGV, &sig_handler);
    f();
}

Ausgabe:

0   a.out                               0x00001f2d sig_handler + 35
1   libSystem.B.dylib                   0x95f8f09b _sigtramp + 43
2   ???                                 0xffffffff 0x0 + 4294967295
3   a.out                               0x00001fb1 h + 26
4   a.out                               0x00001fbe g + 11
5   a.out                               0x00001fcb f + 11
6   a.out                               0x00001ff5 main + 40
7   a.out                               0x00001ede start + 54

Dies bedeutet nicht, Holen Sie sich bonus-Punkte für die optionale Eigenschaften (außer nicht erfordern eine GUI), jedoch hat es den Vorteil, dass Sie sehr einfach, und benötigt keine zusätzlichen Bibliotheken oder Programme.

Andere Tipps

FYI,

die vorgeschlagene Lösung (mit backtrace_symbols in einem signal-handler) ist gefährlich gebrochen.VERWENDEN SIE ES NICHT, -

Ja, Ablaufverfolgung und backtrace_symbols produzieren einen backtrace hinzufügen und übersetzen es zu symbolischen Namen, jedoch:

  1. backtrace_symbols reserviert Speicher mit malloc und verwenden Sie frei, um frei - Wenn Sie abstürzt, weil der Speicher Korruption Ihrer malloc arena ist sehr wahrscheinlich beschädigt und verursachen einen doppelten Fehler.

  2. malloc und kostenlos schützen die malloc-arena mit einer Sperre intern.Sie haben möglicherweise Fehler aufgetreten, die in der Mitte ein malloc/free mit dem Schloss genommen, die bewirkt, dass diese Funktion oder etwas, das Sie aufruft, dead lock.

  3. Verwenden Sie legt die verwendet die standard-stream, das ist auch geschützt durch eine Sperre.Wenn Sie bemängelt in der Mitte eines printf Sie haben wieder eine Sackgasse.

  4. Auf 32-bit-Plattformen (z.B.Ihre normale PC 2 Jahr vor), wird der kernel plant die Rückkehr Adresse an einen internen glibc-Funktion anstelle Ihrer fehlerhaften Funktion in Ihrem Stapel, so dass die wichtigste information, die Sie interessiert sind - in welche Funktion hat das Programm Fehler, tatsächlich beschädigt werden, auf diese Plattform.

So, der code im Beispiel ist die Schlimmste Art von falsch - es SIEHT aus wie es ist zu arbeiten, aber es wird wirklich scheitern Sie auf unerwartete Weise in der Produktion.

BTW, interessieren tut es richtig?check diese aus.

Cheers, Gilad.

Hier ist ein Beispiel, wie man ein paar mehr Infos mit einem demangler.Wie Sie sehen können diese auch Protokolle der stacktrace-Datei.

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <cxxabi.h>

void sig_handler(int sig)
{
    std::stringstream stream;
    void * array[25];
    int nSize = backtrace(array, 25);
    char ** symbols = backtrace_symbols(array, nSize);
    for (unsigned int i = 0; i < size; i++) {
        int status;
        char *realname;
        std::string current = symbols[i];
        size_t start = current.find("(");
        size_t end = current.find("+");
        realname = NULL;
        if (start != std::string::npos && end != std::string::npos) {
            std::string symbol = current.substr(start+1, end-start-1);
            realname = abi::__cxa_demangle(symbol.c_str(), 0, 0, &status);
        }
        if (realname != NULL)
            stream << realname << std::endl;
        else
            stream << symbols[i] << std::endl;
        free(realname);
    }
    free(symbols);
    std::cerr << stream.str();
    std::ofstream file("/tmp/error.log");
    if (file.is_open()) {
        if (file.good())
            file << stream.str();
        file.close();
    }
    signal(sig, &sig_handler);
}

Dereks Lösung ist wahrscheinlich die beste, aber hier ist eine alternative, jedenfalls:

Neuere Linux-kernel-version erlauben Sie auf Rohr core-dumps auf einem Skript oder Programm.Sie könnten ein Skript schreiben, fangen Sie die core-dump, zu sammeln alle zusätzlichen Informationen, die Sie benötigen, und E-mail alles wieder zurück.Dies ist eine Globale Einstellung, so dass Sie würde gelten für alle abstürzenden Programm auf das system.Es wird auch erfordern root-Rechte einrichten.Es können konfiguriert werden durch das /proc/sys/kernel/core_pattern platziert wird Datei.Gesetzt, dass Sie zu so etwas wie '| /home/myuser/bin/my-core-handler-Skript'.

Die Ubuntu-Leute dieses feature nutzen, so gut.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top