GNU/Linux >> Linux の 問題 >  >> Linux

実行可能Cプログラムのエラー情報をStdoutにリダイレクトする方法は? (mac Os X)?

自動Cプログラムチェッカーを作成したい。
たとえば、おもちゃの「hello.c」プログラムがあります:

#include <stdio.h>

int main()
{
    int a, b;

    while (scanf("%d %d", (&a)-1000000000000000, &b) != EOF)
    {
        printf("%d\n", a+b);
    }

    return 0;
}

これが私の入力ファイル「1.in」です:

1 2
4 5
10 10
2 2
3 2
7 4

および出力ファイル「1.out」:

3
9
20
4
5
11

「gcchello.c-ohello.o」を使用して、実行可能プログラム「hello.o」をコンパイルおよび生成します。明らかに、プログラムは「セグメンテーション違反」に遭遇します:(私のMAC OS Xで実行)

$ ./hello.o <1.in
Segmentation fault: 11

しかし、パイプと差分を使用して自動チェッカーを作成したい:

./hello.o <1.in | diff - 1.out

そして、出力は次のとおりです。

0a1,6
> 3
> 9
> 20
> 4
> 5
> 11

エラーメッセージは表示されません!しかし、それらを端末(MAC OS X)に表示したい。

stderrを次のようにstdoutにリダイレクトしようとしています:

./hello.o <1.in 2>&1 | diff - 1.out

しかし、効果はありません!

また、stderrを次のようなファイルにリダイレクトしようとしています:

./hello.o <1.in 2>log

情報「セグメンテーション違反:11」がターミナルに表示されますが、ファイルには何も表示されません。

私が使用するときも同じ状況が発生します

./hello.o <1.in &>log

エラー情報がstderrにない可能性があります。

では、どうすればこの問題を解決できますか?ありがとうございます!

承認された回答:

注: hello.oを置き換えました helloで 、.o以降 このコンテキストでのファイル拡張子は、通常、最終的な実行可能プログラムではなく、オブジェクトファイルを示します。

あなたの投稿によると、あなたはコマンドを実行したいと思います:

./hello <1.in 2>&1 | diff - 1.out

そして、./hello <1.inの実行からのエラーメッセージが必要です。 このコマンドの出力に表示されます。ただし、エラーメッセージはhello.oからのものではありません プログラム自体ですが、シェルからです。 1行で目的の効果を概算するために私が考えることができる最も近いことは、サブシェルでコマンドを実行してから、この出力をdiffで使用することです。 コマンド:

2>&1 bash -c './hello <1.in' | diff - 1.out

これにより、次の出力が得られます。

1c1,6
< bash: line 1: 58469 Segmentation fault: 11  ./hello < 1.in
---
> 3
> 9
> 20
> 4
> 5
> 11

唯一の違いは、この場合、シェルによって出力される追加のメタデータ(つまり、行番号とコマンド文字列)を取得することです。エラーメッセージを正確に複製したい場合は、trapを使用できます。 正確に正しい文字列を印刷するフックを挿入します。

プログラムでエラーメッセージを抽出する方法が見つからなかったため、Bashのソースコードにアクセスして「セグメンテーション違反」メッセージを検索しました。私はそれをsiglist.cというファイルで、他の多くのシグナルやエラーの説明とともに見つけました。その情報を使用して、次のスクリプトを作成しました。

#!/bin/bash 

# trapdesc.sh
#
#   Take an error code from the `trap` command and
#   print out the corresponding error message.
#
#   Example usage:
#
#       (trap 'bash trapdesc.sh $?' EXIT; <COMMAND>)
#

# List of signal codes and corresponding error messages
#
# Taken from bash source (siglist.c):
#
#   https://github.com/tpruzina/bash/blob/master/siglist.c
#
declare -a SIGNALS=(
"SIGHUP":"Hangup"
"SIGINT":"Interrupt"
"SIGQUIT":"Quit"
"SIGILL":"Illegal instruction"
"SIGTRAP":"BPT trace/trap"
"SIGABRT":"ABORT instruction"
"SIGEMT":"EMT instruction"
"SIGFPE":"Floating point exception"
"SIGKILL":"Killed"
"SIGBUS":"Bus error"
"SIGSEGV":"Segmentation fault"
"SIGSYS":"Bad system call"
"SIGPIPE":"Broken pipe"
"SIGALRM":"Alarm clock"
"SIGTERM":"Terminated"
"SIGURG":"Urgent IO condition"
"SIGSTOP":"Stopped (signal)"
"SIGTSTP":"Stopped"
"SIGCONT":"Continue"
"SIGCLD":"Child death or stop"
"SIGTTIN":"Stopped (tty input)"
"SIGIO":"I/O ready"
"SIGXCPU":"CPU limit"
"SIGXFSZ":"File limit"
"SIGVTALRM":"Alarm (virtual)"
"SIGPROF":"Alarm (profile)"
"SIGWINCH":"Window changed"
"SIGLOST":"Record lock"
"SIGUSR1":"User signal 1"
"SIGUSR2":"User signal 2"
"SIGMSG":"HFT input data pending"
"SIGPWR":"power failure imminent"
"SIGDANGER":"system crash imminent"
"SIGMIGRATE":"migrate process to another CPU"
"SIGPRE":"programming error"
"SIGGRANT":"HFT monitor mode granted"
"SIGRETRACT":"HFT monitor mode retracted"
"SIGSOUND":"HFT sound sequence has completed"
"SIGINFO":"Information request"
)

# Make sure we get an integer 
if ! [[ "$1" =~ ^[0-9]+$ ]]; then
    2>&1 echo "Not a signal identifier: $1"
    exit 1
fi

# Convert the signal from the `trap` function value to the signal ID
sid="$(($1 - 128))"

# Make sure the signal ID is in the valid range
if [[ "${sid}" -lt 0 || "${sid}" -gt 40 ]]; then
    2>&1 echo "Unrecognized signal: ${sid}"
    exit 1
fi

# Get the array-index for the signal
index="$((sid-1))"

# Get the signal description
description="$(echo ${SIGNALS[index]} | cut -d: -f2)"

# Print the error description
echo "${description}: ${sid}"

これで、このスクリプトを使用して、次のコマンドを実行できます。

(trap 'bash trapdesc.sh $?' EXIT; ./hello <1.in)

これにより、./hello <1.inを実行した場合と同じ文字列が生成されます。 :

Segmentation fault: 11

しかし今では、その文字列を標準エラー(stderr)からキャプチャして、diffにパイプすることができます。 あなたが望むように:

(2>&1 trap 'bash trapdesc.sh $?' EXIT; ./hello <1.in) | diff - 1.out

これにより、エラーメッセージが当初期待していた標準出力に書き込まれた場合に得られるであろう正確な出力が生成されます。

1c1,6
< Segmentation fault: 11
---
> 3
> 9
> 20
> 4
> 5
> 11

Linux
  1. Linuxで出力をファイルとStdoutにリダイレクトする方法

  2. Stdoutを複数のコマンドに送信する方法は?

  3. プログラムの出力をZipファイルにリダイレクトする方法は??

  1. プログラムをどこからでも実行可能にする方法は?

  2. StderrとStdoutを別のファイルにリダイレクトし、ターミナルに表示するにはどうすればよいですか?

  3. プログラムの出力を入力としてリダイレクトする方法

  1. Ssh – Sshを介してStdoutをリダイレクトしますか?

  2. 出力をファイルと標準出力にリダイレクトする方法

  3. C プログラムを使用してマシンの MAC アドレスを取得する方法は?