セグメンテーション違反時にLinuxでコアダンプを生成する方法


回答:


249

これは、使用しているシェルによって異なります。bashを使用している場合、ulimitコマンドは、コアをダンプするかどうかなど、プログラムの実行に関連するいくつかの設定を制御します。入力した場合

ulimit -c unlimited

次に、そのプログラムは任意のサイズのコアをダンプできることをbashに伝えます。必要に応じて、無制限ではなく52Mなどのサイズを指定できますが、コアファイルのサイズが問題になることはおそらくないため、実際にはこれは必要ありません。

tcshでは、次のように入力します

limit coredumpsize unlimited

21
@lzprgmr:明確にするため:デフォルトでコアダンプが生成されない理由は、制限が設定されていないか、0に設定されているため、コアがダンプされないためです。無制限の制限を設定することにより、コアダンプを常に生成できることを保証します。
Eli Courtwright、2011

6
このリンクはさらに深くなり、Linuxでコアダンプの生成を有効にするためのいくつかのオプションを提供します。唯一の欠点は、一部のコマンド/設定が説明されていないことです。
サルサ、2011

6
bash 4.1.2(1)では、52Mなどのリリース制限を指定できないため、無効な番号のエラーメッセージが表示されます。manページには、「値は1024バイト単位である」と記載されています。
a1an 2012

4
まあ、私は「小さな」OpenGLプロジェクトを持っていました。再度ログインすると、17 GBのかわいいコアファイル(25 GBのパーティション上)が表示されました。コアファイルのサイズを制限することは間違いなく良いことです:)
IceCool

1
@PolarisUser:パーティションが食べられないようにしたい場合は、1ギグなどの制限を設定することをお勧めします。それは、妥当なコアダンプを処理するのに十分な大きさである必要がありますが、残りのハードドライブ領域をすべて使い果たすと脅すことはありません。
Eli Courtwright、2014

60

上記で説明したように、ここで尋ねられる実際の質問は、コアダンプが有効になっていないシステムでコアダンプを有効にする方法です。その質問はここで答えられます。

ハングしたプロセスのコアダンプを生成する方法を学びたいと思っているなら、答えは

gcore <pid>

システムでgcoreが利用できない場合

kill -ABRT <pid>

kill -SEGVを使用しないでください。シグナルハンドラーが頻繁に呼び出され、スタックプロセスの診断が難しくなります。


アボートはセグメンテーションフォルトよりも回復可能である可能性が高い-ABRTので-SEGV、シグナルハンドラを呼び出す方がはるかに可能性が高いと思います。(segfaultを処理する場合、通常はハンドラーが終了するとすぐに再びトリガーされます。)コアダンプを生成するためのより適切な信号の選択は-QUITです。
celticminstrel

32

コアダンプが生成される場所を確認するには、次のコマンドを実行します。

sysctl kernel.core_pattern

または:

cat /proc/sys/kernel/core_pattern

どこ%eプロセス名とで%tシステム時刻は。あなたはそれを変更し/etc/sysctl.confてリロードすることができますsysctl -p

コアファイルが生成されない場合(それをテストする:sleep 10 &およびkillall -SIGSEGV sleep)、次の方法で制限を確認します。ulimit -a

コアファイルのサイズが限られている場合は、次を実行します。

ulimit -c unlimited

無制限にします。

次に、再度テストします。コアダンプが成功した場合、次のようにセグメンテーションエラー表示の後に「(コアダンプ)」が表示されます。

セグメンテーションエラー:11(コアダンプ)

参照:コアダンプ-コアファイルが現在のディレクトリにありませんか?


Ubuntu

Ubuntuでは、コアダンプはApportによって処理され、次の場所にあります。/var/crash/。ただし、安定版リリースではデフォルトで無効になっています。

詳細については、Ubuntuのコアダンプはどこにありますか?

マックOS

macOSについては、「Mac OS Xでコアダンプを生成する方法」を参照してください


3
Ubuntuの場合、通常の動作(コアファイルを現在のディレクトリにダンプする)にすばやく戻すには、「sudo service apport stop」でapportサービスを停止するだけです。また、Docker内で実行している場合、その設定はコンテナ内ではなくホストシステム上で制御されます。
Digicrat

26

最後に、クラッシュする前にgdbをプロセスにアタッチし、segfaultが取得されたときにgenerate-core-fileコマンドを実行しました。これにより、コアダンプが強制的に生成されました。


どのようにgdbをプロセスにアタッチしましたか?
チャニー2013年

6
Ritwik Gに応答して、プロセスをgdbにアタッチするには、gdbを起動して「attach <pid>」と入力します。ここで、<pid>は、アタッチするプロセスのpid番号です。
Jean-Dominique Frattini 2013年

(省略形ge
user202729

新しい質問がある場合は、コメントを求める代わりに、新しい質問をする必要があります
user202729 2018年

奇妙なことに、すでにに設定されulimit -cていunlimitedますが、コアファイルはまだ作成されていません。gdb generate-core-fileセッションのファイルはコアファイルを作成します。
CodyChan

19

たぶんあなたはこのようにそれを行うことができます、このプログラムはセグメンテーションフォールトをトラップする方法のデモンストレーションであり、デバッガーにシェルアウトし(これはで使用された元のコードですAIX)、セグメンテーションフォールトのポイントまでスタックトレースを出力します。Linuxの場合sprintfに使用する変数を変更する必要がありますgdb

#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 */
}

このブログのここに示されているように、コアをダンプするためにgdbを取得するためのパラメーターを追加する必要がある場合があります


16

コアダンプの生成に影響する可能性のあるものは他にもあります。私はこれらに遭遇しました:

  • ダンプのディレクトリは書き込み可能でなければなりません。デフォルトでは、これはプロセスの現在のディレクトリですが、を設定することで変更できます/proc/sys/kernel/core_pattern
  • 一部の条件では、カーネル値/proc/sys/fs/suid_dumpableによってコアが生成されない場合があります。

manページで説明されているように、生成を妨げる状況が他にもありますman core。試してみてください。


9

コアダンプをアクティブにするには、次の手順を実行します。

  1. /etc/profileコメント行:

    # ulimit -S -c 0 > /dev/null 2>&1
  2. /etc/security/limits.confラインアウトのコメント:

    *               soft    core            0
  3. cmd limit coredumpsize unlimitedを実行し、cmd で確認しlimitます。

    # limit coredumpsize unlimited
    # limit
    cputime      unlimited
    filesize     unlimited
    datasize     unlimited
    stacksize    10240 kbytes
    coredumpsize unlimited
    memoryuse    unlimited
    vmemoryuse   unlimited
    descriptors  1024
    memorylocked 32 kbytes
    maxproc      528383
    #
  4. kill -s SEGV <PID>コアファイルが書き込まれるかどうかを確認するには、関連するプロセスをcmdで強制終了できます(コアファイルが書き込まれない場合に備えて、これをチェックとして使用できます)。

    # kill -s SEGV <PID>

コアファイルが作成されたら、関連ファイル(1./2./3。)でコアダンプ設定を必ず非アクティブ化してください。


9

Ubuntu 14.04の場合

  1. 有効なコアダンプを確認します。

    ulimit -a
  2. 行の1つは次のようになります。

    core file size          (blocks, -c) unlimited
  3. そうでない場合:

    gedit ~/.bashrculimit -c unlimitedファイルの最後に追加して保存し、ターミナルを再実行します。

  4. デバッグ情報を使用してアプリケーションをビルドします。

    Makefile内 -O0 -g

  5. コアダンプを作成するアプリケーションを実行します( 'core'という名前のコアダンプファイルは、application_nameファイルの近くに作成する必要があります)。

    ./application_name
  6. gdbの下で実行します。

    gdb application_name core

ステップ3では、ターミナルを「再実行」する方法を教えてください。再起動を意味しますか?
Naveen 2017年

@Naveenいいえ、ターミナルを閉じて新しいターミナルを開くだけulimit -c unlimitedです。一時的な解決策としてターミナルに配置するだけでもよいようです~/.bashrc。変更を有効にするには、ターミナルのレストラートのみ編集が必要なためです。
mrgloom 2017年

4

デフォルトでは、コアファイルを取得します。プロセスの現在のディレクトリが書き込み可能であるか、コアファイルが作成されないかを確認します。


4
「プロセスの現在のディレクトリ」とは、プロセスが実行されたときの$ cwdを意味しますか?〜/ abc> / usr / bin / cat def catがクラッシュした場合、問題の現在のディレクトリは〜/ abcまたは/ usr / binですか?
Nathan Fellman、

5
〜/ abc。コメントは15文字にする必要があります。
マークハリソン

5
これは、SEGVの時点での現在のディレクトリです。また、実際のユーザー/グループとは異なる有効なユーザーやグループで実行されているプロセスは、コアファイルを書き込みません。
Darron、

2

システムコールを使用してプログラムでコアダンプをオンにすることをお勧めしますsetrlimit

例:

#include <sys/resource.h>

bool enable_core_dump(){    
    struct rlimit corelim;

    corelim.rlim_cur = RLIM_INFINITY;
    corelim.rlim_max = RLIM_INFINITY;

    return (0 == setrlimit(RLIMIT_CORE, &corelim));
}

なぜそれが良いのですか?
Nathan Fellman、2018

クラッシュ後に生成されたコアファイル。ulimit -c unlimitedコマンドライン環境で実行する必要はなく、アプリケーションを再実行します。
kgbook

クラッシュするたびにコアダンプが欲しいのではなく、ユーザーが開発者として私に連絡してそれを見たときだけです。100回クラッシュする場合は、コアダンプを100個確認する必要はありません。
Nathan Fellman、2018

この場合、使用するのが良いでしょうulimit -c unlimited。また、marco定義を使用してコンパイルできます。enable_core_dumpリリース時にそのマクロを定義しないと、アプリケーションにシンボルが含まれず、デバッグバージョンでコアダンプが置き換えられます。
kgbook

マクロで修飾されている場合でも、コアダンプを生成する場合は、再実行する前にシェルでコマンドを実行するだけでなく、再コンパイルする必要があります。
Nathan Fellman、2018

1

systemdが設定されている場合、状況が少し異なることに言及する価値があります。通常、セットアップでは、core_patternsysctl値を使用して、コアファイルをパイプ処理します。systemd-coredump(8)。コアファイルサイズrlimitは通常、「無制限」としてすでに構成されています。

その後、次のコマンドを使用してコアダンプを取得できます。 coredumpctl(1)

コアダンプなどのストレージは、 coredump.conf(5)ます。coredumpctlのmanページにコアファイルを取得する方法の例がありますが、簡単に言うと次のようになります。

コアファイルを見つけます。

[vps@phoenix]~$ coredumpctl list test_me | tail -1
Sun 2019-01-20 11:17:33 CET   16163  1224  1224  11 present /home/vps/test_me

コアファイルを取得します。

[vps@phoenix]~$ coredumpctl -o test_me.core dump 16163

0

Ubuntu 19.04

他のすべての回答自体は私を助けませんでした。しかし、次の要約は仕事をしました

~/.config/apport/settings次の内容で作成します。

[main]
unpackaged=true

(これにより、カスタムアプリのコアダンプも書き込むようにapportに指示されます)

チェック:ulimit -c。それが0を出力する場合、それを修正します

ulimit -c unlimited

念のためにapportを再起動してください:

sudo systemctl restart apport

クラッシュファイルがで書き込まれるようになりました/var/crash/。ただし、gdb では使用できません。これらをgdbで使用するには、

apport-unpack <location_of_report> <target_directory>

さらに詳しい情報:

  • 一部の回答では、変更を提案していcore_patternます。このファイルは、再起動時にapportサービスによって上書きされる可能性があることに注意してください。
  • apportを停止するだけではうまくいかなかった
  • ulimit -cウェブの他の回答を試しているときに、値が自動的に変更される場合があります。コアダンプ作成の設定中は、定期的に確認してください。

参照:

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.