質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • C

    3815questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

_close Windows

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 660

kanto

score 13

Windows2012R2 VS2013 で以下C言語のコードをコンパイルして実行すると
2回目の _close にて例外が発生します。

_close前にチェックを行いたいのですが、方法が判りません。

1)C言語でC++のように例外をキャッチする方法
2)ファイル記述子が有効か判断する手段
があるか教えてください。

元のプログラムが汚く、ファイル記述子をクローズ後に初期化するといった
回避ができず、ファイル記述子のクローズ時に対応できる方法を探しています。
Linuxの場合には、例外が発生せずに -1 がシステムコール(close)より帰ります。
また、どのコンパイルオプションでも同様に対応できる方法を探しています。

int main( void ){
   int fh1;

   fh1 = _open( "test.txt", _O_RDONLY );
   _close( fh1 ); /* 1回目 */
   _close( fh1 ); /* 2回目 */
   
}

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

実際試してみました。確かに落ちますね。

まず一つ目、発生しているのはC++とかでいう例外ではありません
いわゆるクラッシュとか、アプリが落ちるといった現象です。
プログラムとして想定外の動作になっているため、
C言語であろうと無かろうと、キャッチする方法はありません。
<del>また、C言語には例外という機能そのものがありません。</del>※
※ただ、この場合は後述の回避策があります。
MSの独自拡張で例外補足できるようです。しらんかった。

次に、なぜクラッシュするかですが、MSDN:_closeに書いてあるとおり、
fdについて不正かどうかについて、MSDN:パラメーターの検証に書いてある検証を行います。
既に閉じたfdだったなど不正だった場合のデフォルトの動作はクラッシュです。
ただ、この動作は変更できます。
MSDN:_set_invalid_parameter_handlerの記載の通り、
_set_invalid_parameter_handlerを用いて動作を変えれば、クラッシュしません。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <stdlib.h>
void myHandler(
    const wchar_t* expression,
    const wchar_t* function,
    const wchar_t* file,
    unsigned int line,
    uintptr_t pReserved)
{
    // 何もしない
}
int main(void){
    int fh1;
    _set_invalid_parameter_handler(myHandler);
    fh1 = _open("test.txt", _O_RDONLY);
    printf("1st: %d\n", _close(fh1)); /* 1回目 */
    printf("2nd: %d\n", _close(fh1)); /* 2回目 */
    return 0;
}
上のコードはクラッシュせずに
1st: 0
2nd: -1
と出力されると思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/10 23:22

    ご回答いただき、ありがとうございます。
    私の方でも確認できました。

    何分古いソースで、手が入れられない状況でしたので
    今回のような対応が必要でした。

    もちろん、問題は上位層に問題がありますので、時期を見て
    修正するようにいたします。

    キャンセル

+1

try-except で Cでも例外は捕捉できますが、そのように解決すべきではありません。
なぜなら、1回目と2回目のclose の間に、なにかあなたがハンドルを使ったり、
ライブラリを使用したら、1回目でクローズされたハンドル番号が再利用されてしまい、
2回目で、何事もなかったようにクローズされてしまい、しばらくたった後に、ライブラリの処理を
おこなったらエラーになったり、デバッグの非常に難しい、わけのわからない問題が
発生し始めます。

>元のプログラムが汚く、ファイル記述子をクローズ後に初期化するといった 回避ができず、
Linux 上で -1 が返ってきて何とか動いているようでも、元のプログラムを直すべきです。
Windows では、作った人が親心で、「こんなことはしてはいけないよ」と正しくエラーに
なるようになっているのですから。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/10 23:24

    ご回答いただき、ありがとうございました。
    私の質問が悪く、例外時のハンドリングでは無く、クラッシュ時のハンドリングでした。

    ご指摘いただいていることは重々承知しており、元のプログラムを修正するべきなのは自明ですが、直ぐに対応できない状況です。時期をみて対応いたします。

    キャンセル

0

リファレンスのサンプルを見ても分かりますが、戻り値でハンドルが有効かどうか判定できます。

有効の場合は1回だけ _close の対象になります。(2回目にはハンドルは既に破棄されているので、有効なハンドルではありません)

動作の詳細は、リファレンスをよく読んでみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/10 22:24

    ご回答いただき、ありがとうございます。

    確かにリファレンスには、戻り値で判断できるようですが、
    実際には例外が発生して、プログラム自体がハングアップいたします。

    そのため、関数のコール前に判断できる方法を探しております。

    キャンセル

  • 2015/08/10 22:33 編集

    戻り値で -1 が帰った時点で、ハンドルは取得できなかった。ということになります。
    なので、そのまま処理を続けることはできません。

    まずハンドルが取得できなかった理由を特定する必要があります。
    すくなくとも、そのまま処理を続けることはできません。

    ちなみに、質問のコードの場合、カレントディレクトリに指定のファイルがない場合openに失敗します。失敗した場合は、当然その後の処理はできません。close関数もハンドルが不正なので例外を出すでしょう。
    他の回答者の方も指摘されていますが、C言語は一般的に例外処理でエラー・ハンドリングする場面は限られます。
    そのあたりについても、利用するライブラリの作りをよく確認することをお勧めします。

    キャンセル

  • 2015/08/10 22:43

    あと質問のコードのままですと、戻り値が -1 だった場合の処理が書かれていません。
    -1 だった場合 close関数は利用できないので、-1でなかった場合だけ 後処理として closeを呼ぶようにしないと、質問者さんの言われるように落ちます。

    キャンセル

  • 2015/08/10 23:25

    ご回答いただき、ありがとうございます。
    無事解決いたしました。ご対応いただき、ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    jQuery UI Dialog - ダイアログ内でスクロールしている間に親ページがスクロールしてし...

    jQuery UI dialogを使ってページのポップアップを表示します。ポップアップ内をスクロールしていて、下までスクロールバーが来ると、親ページがスクロールし始めます。ダイアロ

  • 受付中

    JTableを用いたメモ帳の「Save/Open」機能の実装

    現在、JavaのSwingでJTableを用いたメモ帳を作っています。(前回の質問) 文字のフォントや行の追加・削除といった機能の実装ができ、次に「Save/Open」機能の実装

  • 解決済

    【Java】ストリームのクローズ処理について

    Javaのストリームのクローズ処理について、通常下記の通りとなるかと思います。         BufferedWriter out = null;         try {

  • 受付中

    java JARでのフォルダ読み込み

    現在作成したプログラムを.jarにさせて動かそうとしたのですが、フォルダの読み込みが上手くいかず、起動することができません。 どうやらフォルダを読み込むBufferedReade

  • 受付中

     コードの添削

    Java開発初心者です。 ※質問内容を編集しました 以下のコードについて質問です。 質問①なぜ配列が必要なのでしょうか。 質問②while文はなにをしているのでしょうか

  • 解決済

    ファイルの処理について。

    前提 書籍で勉強している学生です。 書籍の解答がないため問題のヒントや解説をしていただけると嬉しいです。 問題 キーボードからファイル名を読み込んで、その名前のファイルの中身を

  • 解決済

    シリアライズ時のcsvの文字化け

    やりたいこと: 総務部のリーダー田中太郎(41歳)のインスタンスをJVM内に生成したうえで直列化機構を使ってファイル【C:\Users\☆☆☆\Desktop\test用3.csv

  • 受付中

    システムコールdupについて

    自分は今OSを勉強していて、その一環としてシステムコールを勉強しています。 MINIXを教材としています。 DUPシステムコールがどのような動作をするのかはなんとなくイメージできる

同じタグがついた質問を見る

  • C

    3815questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。