Qiita の「C言語のreturn 0の有用性が今更わかった話」という記事を読んで疑問に思ったので質問させてください。 C または C++ のmain()関数の戻り値 return 0 の実用的な使い方とは何でしょうか? また、それをどう実装するのでしょうか?
気付いたのですが、リンク先の例では、return 0 (異常なし)の場合に「OK」と出力され、逆に、return 1(異常あり)の場合に無言であります。これは「UNIXという考え方 The UNIX philosophy」に引用してある5つ目の定理「5.Silence is golden. 沈黙は金 」に反してしまいます。
$ ./a.out && echo "OK"
は、使い方の1つであり他にも使い方はたくさんあると考え、あれこれ思索してみた用法は、0 以外が戻ってきたら…
- ログを書く。
- 非常用の代替サービス等が起動する。
- 管理者にメールが送信される。
などですが、実際にこれをどう実装するかは検討も着きません。 皆さんのアイデア、使用経験、それをどう実装した、または これに詳しい書籍があれば紹介していただけますか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答6件
0
気付いたのですが、リンク先の例では、return 0 (異常なし)の場合に「OK」と出力され、逆に、return 1(異常あり)の場合に無言であります。
リンク先は一部のことしか書かれていないので、あまり参考にならないかもしれません。&&
は左側のコマンドが成功したら右側のコマンドを実行するというものですが、当然のことながらその逆もあります。||
でコマンドをつなげると、左側のコマンドが失敗(終了ステータスが0以外)したら右側のコマンドを実行します。
つまり、
$ ./a.out || echo "NG"
こうすれば、a.outが失敗したらNGと表示されます。
バッチ処理や自動化においては、単にコマンドを順番に実行するだけでなくコマンドの実行結果に応じて処理を変えたいこともあります。そのため、シェルには条件分岐やループ制御などの複雑な処理を行うための命令が多数用意されています。コマンドの終了ステータスはそういうときになくてはならないものです。
どういうことができるのか(どうやって書くのか)、お使いのシェルがbash
ならこのmanページが役に立つかもしれません。全機能の説明が書かれていて長いのですが、そのページの「リスト」と「複合コマンド」がご質問に該当する部分です。
投稿2017/08/09 00:25
総合スコア5938
0
C や C++ といった言語に関係なく戻り値 0 が正、0 以外の値がエラー扱いというのが一般的な使われ方です。一部 Plan9 の様に数値の終了ステータスを持たない物もあります。
0 と 0 以外の値を返せるのですが実はそれくらいしか取り決めが無く、人によって引数異常系は -1 にしたり 2 にしたりする人もいます。また物によってはビットマスクで終了時の状態を表すという方法も使われます。fsck コマンドが1例です。
0 - No errors 1 - File system errors corrected 2 - System should be rebooted 4 - File system errors left uncorrected 8 - Operational error 16 - Usage or syntax error 32 - Fsck canceled by user request 128 - Shared library error
fsck の終了ステータスは値を見ればそれがどういう状態で終了したのかがだいたい分かる様になっています。他の方が書いていますがシェルスクリプトでは set -e
を書いておくと子プロセスの終了ステータスを判定して 0 以外であれば処理を継続しない様になっています。また bash では $?
で直前に起動したプロセスの終了ステータスを得る事が出来ます。Windows のコマンドプロンプトの場合は %ERRORLEVEL%
で判定出来ます。
プログラミング言語を使ってシステムを作る場合、終了ステータスは「自プロセスを起動した親プロセスに『これ以上処理を継続しないでくれ』と通知する為の手段」ですので、これはおまじないでも魔法でもなんでもなく、当たり前に考慮しないといけない話になります。
なお exit(0) でも同様の働きをしますが、C++ の場合は main 関数のスコープに定義されたオブジェクトのデストラクタが実行された後に値が返ります。かたや exit(0) はメモリの解放など無く突然終了します。(atexit という関数で exit 時に呼び出す関数を事前に登録する事も出来ます)
投稿2017/08/09 04:42
編集2017/08/09 08:06総合スコア5030
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
シンプルかつ強力な使い方として、set -e
があります。シェルスクリプト内でset -e
としておくと、終了コードが0以外のコマンドが来た場合に、そこでシェルスクリプト自体を終了するようになります。
投稿2017/08/08 22:19
総合スコア145186
0
こんにちは。
mainからのreturnで返却する値は、プロセスの終了ステータスになります。これは親プロセスが受け取ることができます。
子プロセスがエラー終了したのか正常終了したのか、知りたいことは良くあると思います。サブルーチンを呼び出して、それがエラー終了するようなものなら、やはりエラー知りたいですよね? それと同じことです。
私自身はエラーが戻ったらメッセージを表示して終了し、インストールミスがないか確認して貰うような使い方くらいしかしてないです。
巨大なシェルスクリプトを作る人たちは、もしかすると積極的に使っているかも知れません。
投稿2017/08/08 18:01
総合スコア23272
0
「コマンドの戻り値をどう使うの?」という質問でしょうか?
例えば、Bashのif
構文は、
Bash
1if コマンド 2then コマンドの戻り値が0のときに実行する処理 3else コマンドの戻り値が0でないときに実行する処理 4fi
ですので、「指定文字列がファイルにあれば戻り値0で、無い場合は戻り値1」というgrep
コマンドを使って、
Bash
1if grep FOO bar.txt >/dev/null 2then echo FOO が bar.txt の中にあった 3else echo FOO が見つからなかった 4fi
のように出来ます。
外部コマンドでなく、Bashの内部コマンドですが、read
は、「入力がEOFでなければ戻り値0で、入力がEOFなら戻り値1」というコマンドで、while
構文は、「while
の後のコマンドが戻り値0の間、ループを実行して、戻り値が0でなければループ終了」なので、
Bash
1while read line 2do echo $line 3done < textfile
で、ファイル内容を表示出来ます。
他にも、直近のコマンドの戻り値は$?
で参照出来るので、戻り値が1の場合と2の場合で処理を分けたりも出来ます。
例えば、上に書いたgrep
では、文字列が見つからなかったときに戻り値1で、指定したファイルが存在しなかった場合には戻り値2です。
Bash
1grep -q -s FOO bar.txt 2case $? 30) echo bar.txt に FOO があった 4 ;; 51) echo bar.txt に FOO が無かった 6 ;; 72) echo そもそもbar.txtが読めなかった 8 ;; 9esac
投稿2017/08/08 23:49
総合スコア84618
0
ベストアンサー
皆さんのアイデア、使用経験、それをどう実装した
cプログラムはバッチ処理に多用している関係で、クーロン起動、画面起動等の自動運転処理中でリターンコードは使っています。、コードには意味を持たせ(0,1,3...)、ご提示された項目への振り分けを行っています。
ログを書く。(異常時の際のデータベース、ネットワーク、データ不整合のログを出力)
非常用の代替サービス等が起動する。(リトライ実行、スキップ、中断、初期戻し)
管理者にメールが送信される。(夜中や休日に送られて来ます、即時対応、次回対応)
これらを行う判断としてリターンコードに意味を持たせ、データベースやネットワークに異常、業務的不整合が発生した場合、処理を中断、継続等させる判断をしております。
特にログは非常に重量となります。発生時点のこれが無いとリカバリー方法や判断が難しいです。
まれですがプログラムで判定をさせて、リターンコードで以降の処理の流れをコントロールする場合に使ったりしています。
投稿2017/08/08 23:29
総合スコア4070
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/08/09 16:03