• 締切済み

HANDLE無効について

C言語初心者のy_615_tと申します。 秀丸というエディタで作っているソースを Visual Studio.NET(2005)でコンパイルしています。 環境はwindowsXPです。 現在Win32APIをつかってプログラムを作っています。 2つのファイルを用意し、以下の状態を作ります。 (1)2つともない時 (2)1つめだけある時 (3)2つめだけある時 (4)2つともある時 この状態のとき、以下の処理をします。 (1)のとき、1つ目のファイルを作り、ファイルに書き込む (2)のとき、1M以下なら続きから書き込む      1M以上なら2つ目のファイルを作り、書き込む (3)のとき、(2)と同様 (4)のとき、サイズを比較して書き込む      サイズが同じ時、更新日時で比較して新しい方に書き込む というプログラムを作りたいのですが、HANDLEが無効というエラーが出てしまいます。 サイズ・更新日時の取得に ・GetSizeFile ・GetFileTime を使っているので、エラーが起こるのかなと思ったのですが、 上手く動作しません。 最初にファイルがルカのチェックをする際にサイズと時間をとっていて、処理の際に、比較しています。 書込みのWriteFileは外部関数として私が作ったものを呼び出しています。HANDLEのエラーは書込みの際起きているのですが、 HANDLEをexternでmainと外部関数で使うことは問題があるのでしょうか。教えてください。

みんなの回答

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.6

続き。 // ファイルが2つともない時 void WRITE_FILE0( LPWRITE_WORK w ) {  w->hFile1 = CREATE_FILE_NEW( Drct[0] );  SetFilePointer( w->hFile1, 0, NULL, FILE_BEGIN );  HANDLE_WRITE1( w ); } // ファイルが1つ目だけある時 void WRITE_FILE1( LPWRITE_WORK w ) {  if ( w->Size <= 1000 ){   SetFilePointer( w->hFile1, 0, NULL, FILE_END );   HANDLE_WRITE1( w );  }  else{   //CloseHandle( w->hFile1 );   w->hFile2 = CREATE_FILE_OPEN( Drct[1] );   SetFilePointer( w->hFile2, 0, NULL, FILE_BEGIN );   HANDLE_WRITE2( w );  } } // ファイルが2つ目だけある時 void WRITE_FILE2( LPWRITE_WORK w ) {  if ( w->Size <= 1000 ){   SetFilePointer( w->hFile2, 0, NULL, FILE_BEGIN );   HANDLE_WRITE2( w );  }  else{   //CloseHandle( w->hFile2 );   w->hFile1 = CREATE_FILE_OPEN( Drct[0] );   SetFilePointer( w->hFile1, 0, NULL, FILE_BEGIN );   HANDLE_WRITE1( w );  } } // ファイルが両方ある時 void WRITE_FILE3( LPWRITE_WORK w ) {  if ( w->Size < w->Size2 ){   if ( w->Size <= 1000 ){    SetFilePointer( w->hFile1, 0, NULL, FILE_END );    HANDLE_WRITE1( w );   }   else{    //CloseHandle( w->hFile1 );    w->hFile2 = CREATE_FILE_EXISTING( Drct[1] );    SetFilePointer( w->hFile2, 0, NULL, FILE_BEGIN );    HANDLE_WRITE2( w );   }  }  else if ( w->Size > w->Size2 ){   if ( w->Size2 <= 1000 ){    SetFilePointer( w->hFile2, 0, NULL, FILE_END );    HANDLE_WRITE2( w );   }   else{    //CloseHandle( w->hFile2 );    w->hFile1 = CREATE_FILE_EXISTING( Drct[0] );    SetFilePointer( w->hFile1, 0, NULL, FILE_BEGIN );    HANDLE_WRITE1( w );   }  }  else if ( w->Size == w->Size2 ){   ft = CompareFileTime( &ft_b, &ft_b2 );      if ( ft == +1 ){    if ( Size <= 1000 ){     SetFilePointer( w->hFile1, 0, NULL, FILE_END );     HANDLE_WRITE1( w );    }    else{     //CloseHandle( w->hFile1 );     w->hFile2 = CREATE_FILE_EXISTING( Drct[1] );     SetFilePointer( w->hFile2, 0, NULL, FILE_BEGIN );     HANDLE_WRITE2( w );    }   }   else if ( ft == -1 ){    if ( w->Size2 <= 1000 ){     SetFilePointer( w->hFile2, 0, NULL, FILE_END );     HANDLE_WRITE2( w );    }    else{     //CloseHandle( w->hFile2 );     w->hFile1 = CREATE_FILE_EXISTING( Drct[0] );     SetFilePointer( w->hFile1, 0, NULL, FILE_BEGIN );     HANDLE_WRITE1( w );    }   }   else{    printf( "error\n" );   }  } }

y_615_t
質問者

お礼

おそくなりました。 本当に本当にありがとうございます!! 解決しました!! とても細かく説明してくださり、大変勉強になりました。 きちんと勉強したいと思います。 ありがとうございました。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.5

★アドバイス >HANDLEをexternでmainと外部関数で使うことは問題があるのでしょうか。  ↑  これには問題はないと思います。  それよりも HANDLE_OPEN() 関数が長いので分かりやすく複数のサブ関数に  処理を分けたほうが良いでしょう。例えば  switch ( y * 2 + x ){   case 0: // ファイルが2つともない時   case 1: // ファイルが1つ目だけある時   case 2: // ファイルが2つ目だけある時   case 3: // ファイルが両方ある時  }  という感じで。 ・あと CreateFile() 関数の部分はマクロ関数を定義して分かりやすくしてみます。  #define CREATE_FILE_NEW(s) …  #define CREATE_FILE_OPEN(s) …  #define CREATE_FILE_EXISTING(s) …  という感じで。  その他、CreateFile() 関数の戻り値をチェックしてみて下さい。  それからどこまで(どの動作まで)は正常に書き込んでいるのかをチェックして下さい。 >ファイルは作れたのですが、 >2つのファイルが1kBでとまり、それ以降書き込めなくなってしまいます。  ↑  これってソースにある >if(Size<=1000){  とか >if(Size2<=1000){  の 1000 が原因ではないの?  質問では 1M(バイト)ですよね。それならば  if ( Size <= (1024 * 1024) ){  じゃなのかな?  それとも Size は KB 単位なのでしょうか? ・とにかく下に4つのサブ関数と1つの HANDLE_OPEN() に分けたものを載せておきます。  これを元にコンパイル可能な状態に修正してから調査して下さい。  どの関数のどの場所までは正常か、ここから異常かなど。 // break 付きの case キーワード #define CASE   break;case #define DEFAULT break;default // マクロ関数 #define CREATE_FILE(s,n)      CreateFile(s,GENERIC_WRITE|GENERIC_READ,0,NULL,n,FILE_ATTRIBUTE_NORMAL,NULL) #define CREATE_FILE_NEW(s)    CREATE_FILE(s,CREATE_NEW) #define CREATE_FILE_OPEN(s)   CREATE_FILE(s,OPEN_ALWAYS) #define CREATE_FILE_EXISTING(s) CREATE_FILE(s,TRUNCATE_EXISTING) // 作業変数の構造体を宣言 typedef struct WRITE_WORK {  HANDLE hFile1;  HANDLE hFile2;  DWORD Size1;  DWORD Size2;   :  その他、必要ならば記述   : } WRITE_WORK, *LPWRITE_WORK; // 関数のプロトタイプ宣言 extern void HANDLE_WRITE1( LPWRITE_WORK w ); extern void HANDLE_WRITE2( LPWRITE_WORK w ); extern void WRITE_FILE0( LPWRITE_WORK w ); extern void WRITE_FILE1( LPWRITE_WORK w ); extern void WRITE_FILE2( LPWRITE_WORK w ); extern void WRITE_FILE3( LPWRITE_WORK w ); // 見やすく書き直し void HANDLE_OPEN( void ) {  WRITE_WORK w;  int x, y;    // ここにファイルがあるかのチェックの処理  w.Size1 = 記述;  w.Size2 = 記述;    // 状況で分岐  switch ( y * 2 + x ){   CASE 0: WRITE_FILE0( &w ); // ファイルが2つともない時   CASE 1: WRITE_FILE1( &w ); // ファイルが1つ目だけある時   CASE 2: WRITE_FILE2( &w ); // ファイルが2つ目だけある時   CASE 3: WRITE_FILE3( &w ); // ファイルが両方ある時  }  CloseHandle( w.hFile2 );  CloseHandle( w.hFile1 ); } 次の回答へ続く。

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.4

>2つのファイルが1kBでとまり、それ以降 おそらく1KBも書き込まれていません。。。 1KBというのは恐らくディスク上のサイズに過ぎず、 実際にファイルのプロパティからみれば 数バイト程度書き込まれている程度でしょう。 ハンドルがグローバル変数になっているのですが、 見たところ通信処理などがありそうですが、 スレッドなどは使用していないのでしょうか? >HANDLE_WRITE 上記の関数で失敗しているということでしょうか? とりあえず、GetLastErrorの値を随所に出力するようにし、 何の関数が、どの様なエラーコードで終了しているかを 調べることが重要です。

y_615_t
質問者

お礼

そうでした。 2つのファイルともに1KBでとまり、それ以降は何も出来ない状態でした。 スレッドの入ったプログラムにこの処理を入れようとしています。 正常に動くか、まずは小さいものを作ろうと思い、はじめました。 エラーはHANDLE_WRITE関数でおこっていて、ハンドルが無効という6番のエラーでした。 ご指摘ありがとうございました。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

> ハンドルを閉じなかったのですが、いけないようですね。 解決したのでしょうか? まあそれはおいときまして、コードを見せてくれと言ったのは 実際にAPIを呼び出していたり、ハンドルを渡している部分なんですが(^^;

y_615_t
質問者

補足

#include<stdio.h> #include<winsock2.h> #include<ws2tcpip.h> #include<windows.h> #include<stdlib.h> #include<winbase.h> //#define BUFFER_SIZE 256 extern void HANDLE_WRITE(void); extern void HANDLE_WRITE2(void); HANDLE hFile; HANDLE hFile2; void HANDLE_OPEN() { /*ここに宣言とファイルがあるかのチェックの処理が入ります。*/ /*状況を作る*/ /*ファイルが2つともない時*/ if(x==0&&y==0){ flag=0; } /*ファイルが1つ目だけある時*/ else if(x==1&&y==0){ flag=1; } /*ファイルが2つ目だけある時*/ else if(x==0&&y==1){ flag=2; } /*ファイルが両方ある時*/ else if(x==1&&y==1){ flag=3; } /*フラグ別の処理*/ if(flag==0){ hFile=CreateFile(Drct[0],GENERIC_WRITE|GENERIC_READ,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL); SetFilePointer(hFile,0,0,0); HANDLE_WRITE(); } else if(flag==1){ if(Size<=1000){ SetFilePointer(hFile,0,0,2); HANDLE_WRITE(); } else{ //CloseHandle(hFile); hFile2=CreateFile(Drct[1],GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); SetFilePointer(hFile2,0,0,0); HANDLE_WRITE2(); } } else if(flag==2){ if(Size<=1000){ SetFilePointer(hFile2,0,0,2); HANDLE_WRITE2(); } else{ //CloseHandle(hFile2); hFile=CreateFile(Drct[0],GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); SetFilePointer(hFile,0,0,0); HANDLE_WRITE(); } } else if(flag==3){ if(Size<Size2){ if(Size<=1000){ SetFilePointer(hFile,0,0,2); HANDLE_WRITE(); } else{ //CloseHandle(hFile); hFile2=CreateFile(Drct[1],GENERIC_WRITE|GENERIC_READ,0,NULL,TRUNCATE_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); SetFilePointer(hFile2,0,0,0); HANDLE_WRITE2(); } } else if(Size>Size2){ if(Size2<=1000){ SetFilePointer(hFile2,0,0,2); HANDLE_WRITE2(); } else{ //CloseHandle(hFile2); hFile=CreateFile(Drct[0],GENERIC_WRITE|GENERIC_READ,0,NULL,TRUNCATE_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); SetFilePointer(hFile,0,0,0); HANDLE_WRITE(); } } else if(Size==Size2){ ft=CompareFileTime(&ft_b,&ft_b2); if(ft==+1){ if(Size<=1000){ SetFilePointer(hFile,0,0,2); HANDLE_WRITE(); } else{ //CloseHandle(hFile); hFile2=CreateFile(Drct[1],GENERIC_WRITE|GENERIC_READ,0,NULL,TRUNCATE_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); SetFilePointer(hFile2,0,0,0); HANDLE_WRITE2(); } } else if(ft==-1){ if(Size2<=1000){ SetFilePointer(hFile2,0,0,2); HANDLE_WRITE2(); } else{ //CloseHandle(hFile2); hFile=CreateFile(Drct[0],GENERIC_WRITE|GENERIC_READ,0,NULL,TRUNCATE_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); SetFilePointer(hFile,0,0,0); HANDLE_WRITE(); } } else{ printf("error\n"); } } } CloseHandle(hFile); CloseHandle(hFile2); return ; } ファイルは作れたのですが、 2つのファイルが1kBでとまり、それ以降書き込めなくなってしまいます。

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.2

>GetSizeFile こんな関数WIN32APIにあったかな。。。? GetFileSize? >HANDLEをexternでmainと外部関数で使うことは問題があるのでしょうか 在ります。 例としては、そのプロセスが複数実行された場合やファイルIOが遅延した場合などに発生します。同じプロセス内でもスレッド内で書き込みを 行っていたりするとなる場合があります。 Globalにハンドルを持つならばしっかり排他制御する必要があります。 オープン状態で書き込みを続ける場合は今回のように2つのファイルを ロテートさせる必要がありますが、ファイル(HANDLE)をきちっと閉じたりしていますか?そうでない場合も今回のようなことが起こりえます。 #もう少し具体的にコードなどがあると良いと思います。。。

y_615_t
質問者

お礼

早速のご回答、ありがとうございます。 >こんな関数WIN32APIにあったかな。。。? >GetFileSize? すみません。GetFileSizeです。 >在ります。 >例としては、そのプロセスが複数実行された場合やファイルIOが遅延した場合などに発生します。同じプロセス内でもスレッド内で書き込み>を >行っていたりするとなる場合があります。 >Globalにハンドルを持つならばしっかり排他制御する必要があります。 >オープン状態で書き込みを続ける場合は今回のように2つのファイルを >ロテートさせる必要がありますが、ファイル(HANDLE)をきちっと閉じ>たりしていますか?そうでない場合も今回のようなことが起こりえます。 ファイルを開いた状態で書込みを続けたいのですが、HANDLEをとじてしまうとその値がなくなって、処理のサイズチェックの時に動かなくなってしまっていたのでハンドルを閉じなかったのですが、いけないようですね。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

CreateFileでファイルを開いたときそのハンドルは正常なもので GetFileSizeとGetFileTimeに対してそのハンドルを 渡したときは正常動作しているということで良いですか? で、 > 書込みのWriteFileは外部関数として私が > 作ったものを呼び出しています。HANDLEのエラーは書込みの際起きているのですが、 > HANDLEをexternでmainと外部関数で使うことは問題があるのでしょうか。教えてください。 API の WriteFileを使わずに書き込みしているということでしょうか? その自作しているというWriteFileでどうやってファイルを書き出しているのか コードを見せてもらえませんか?

y_615_t
質問者

お礼

ご回答ありがとうございます。 助かります。 >CreateFileでファイルを開いたときそのハンドルは正常なもので >GetFileSizeとGetFileTimeに対してそのハンドルを >渡したときは正常動作しているということで良いですか? はい。ハンドルの値も見ましたが値は同じでした。 出力してみましたが、時間も表示されました。 >API の WriteFileを使わずに書き込みしているということでしょうか? >その自作しているというWriteFileでどうやってファイルを書き出しているのかコードを見せてもらえませんか? すみません。書き方が悪かったようです。 APIのWriteFileをつかっています。同じモジュール内だと処理が多くなってしまうので、別にしてあるだけです。 メインの処理がコレです。 #include<stdio.h> #include<winsock2.h> #include<ws2tcpip.h> #include<windows.h> #include<stdlib.h> #define BUFFER_SIZE 256 extern void HANDLE_OPEN(); char name[BUFFER_SIZE]; int main() { int count; for(count=0;count<5;count++){ memset(name,0,sizeof(name)); printf("書き込みたい文字を入力して下さい\n"); scanf("%s",&name); HANDLE_OPEN(); } return 0; }

関連するQ&A

  • 挿入されているFDはライトプロテクトが掛かってる?

    ライトプロテクトを掛けた状態(「つめ」を開けてあると言うのかな)のFDへWriteFile関数を実行すると、ERROR_WRITE_PROTECTが返ってくるかと思います。 WriteFile関数以外で、FDDに挿入されているFDがライトプロテクトが掛かっているのか調べる方法はあるのでしょうか? (WriteFile関数だと、もし、ライトプロテクトが掛かっていないFDが挿入されていたら書き込んでしまいますよね。FDの中身にはなんら影響を与えることなく、ライトプロテクトが掛かっているか調べる方法ってあるんでしょうか?) 宜しくお願いします。

  • HANDLEの宣言でのエラー

    現在C言語でプログラムを作成しています. シリアル通信を行うプログラムなのですが,エラーが出てしまい, ネットなどで検索してみたのですが,解決できませんでしたので,ご存知の方がいましたら,教えてください. エラーは以下のとおりです. [test.h] #ifndef INCLUDED_TEST_H #define INCLUDED_TEST_H HANDLE handle; HANDLE sirial(char ,char); void sirial_(HANDLE); #endif 上の用にヘッダファイルを作成し,グローバル変数の宣言・プロトタイプ宣言を行おうとすると型がHANDLEのところでエラーが出てしまいます. main関数と同じファイル内で宣言,定義した場合はエラーはでません. ヘッダファイルのように別ファイルに宣言するとエラーとなってしまうのです. 環境は Windows XP SP2 visual studio .net です. よろしくお願いします.

  • [Haskell]handle関数がうまくいかない

    RealWorldHaskellという本を読んでいて解決できないところがあったので質問します。 Control.Exceptionには例外を扱うhandle関数というものがあります。 型シグネチャは Exception e => (e -> IO a) -> IO a -> IO a です。 1つ目の引数に例外を捉えた場合実行する関数を、2つ目の引数に例外を投げる可能性のある関数を与えます。 1つ目の引数の関数の返り値の型と2つ目の引数の型は同じでなければなりません。 次の関数はhandle関数を利用して安全にファイルサイズを取得する(つもりで作った)関数です。 getFileSize :: FilePath -> IO (Maybe Integer) getFileSize path = handle (\_ -> return Nothing ) $ bracket (openFile path ReadMode) hClose $ \h -> do size <- hFileSize h return (Just size) この関数がうまくいきません。 具体的に言えばコンパイルすると handle (\_ -> return Nothing ) の部分で Ambiguous type variable `e0' in the constraint: とエラーは吐きます。 しかし、返り値の型はNothingでMaybe Integerと合致していると思います。 なのにAmbiguousです。 なぜこうなるのかわかりません。 ちなみにControl.OldExceptionでもhandle関数が定義されていますが、ghcのバージョンが新しいせいか(7.0.2)コンパイルできません。 なのでControl.Exceptionしか使えません。 よろしくお願いします。

  • Dirで求めたファイルの更新日時など

    VB6.0です。 Dir関数でファイル名を求めています。 求めたファイルのサイズ、作成日、更新日時を知りたいのですがどのようにしたら良いでしょうか。 よろしくお願いいたします。

  • 更新日時などを変更または参照する方法。

    ファイルを右クリックして作成日時/更新日時/アクセス日時などの情報は ファイルのどこに保存されているのか教えてください。 フリーソフトなどで変更できるソフトがあるのですがどうやって実現しているのか知りたいのです。ファイルをダンプして比較してみたのですがどこにもそれらしい所が見つかりませんでした。 もし可能であればプログラムからその属性を比較して更新日が違う場合エラーなどの処理をさせたいのですが、その方法などもアドバイスいただきたいです。

  • ハンドルが取られやすく、不安定

    こんにちは、私はマークIIクオリスに乗っておりタイヤサイズは195/60/15を履いていたのですが、先日タイヤを225/40/18サイズにかえました。元々アライメントが狂っているせいか、ハンドルを離すとかなり左に寄っていってしまう状態でした。そのためタイヤを変えた際に左側のタイロッドを二回転分ぐらい伸ばし左側のトーインを強くしてみました。 その後からなのですが、今までより左に寄っていく現象は無くなったものの、路面のちょっとした凸凹で今までよりかなりハンドルが取られやすくなったり、ハンドルをいっぱいに切った時にいままではハンドルを放すと自然と直進にもどってきたものが戻らなくなりました。 これらの現象はタイヤの幅が広くなった為なのでしょうか?それともトーを調整した事が悪影響を及ぼしているからなのでしょうか? ご指導よろしくお願いします。

  • アイコンの整列

    ファイルの並べ替えをするとき右クリックしてアイコンの整列するのですがその際選択肢が名前、サイズ、種類、更新日時の四つになる時と名前、サイズ、種類、アーティスト、アルバムのタイトル、年、長さになるときと二種類あります 名前、サイズ、種類、更新日時の四つになってほしいのですが設定等が違うのでしょうか どこをどう変えればそっちになるのでしょうか

  • コマンドでファイルコピーする際の日時比較

    コマンドでファイルコピーする際の日時比較 フォルダAにTEST.TXT(…(1))、フォルダBにもTEST.TXT(…(2))というファイルがあります。 コマンドでフォルダBからフォルダAにコピーする際、 (1)と(2)の更新日時を比較し、(1)のファイルの方が古かったら、 (1)をリネームし、(2)をコピーするという処理を行いたいのですが、可能でしょうか? (更新日時が同じ場合は何もしない。) 使用上のOSはXP Proです。 宜しくお願い致します。

  • ハンドルされていない例外とアクセス違反

    ハンドルされていない例外とアクセス違反 .NET2003のMFCでプログラムをしたところ上記のエラーが発生しました。 ビルドが通ったのでデバッグしたところ、"(mfc71d.dll) でハンドルされていない例外が発生しました""書き込み中にアクセス違反が発生しました"となりました。 また、自分ではプログラムしていないcppファイル中、以下の"{"の所でデバッグが止まってしまいました。 CSyncObject::CSyncObject(LPCTSTR pstrName) { UNUSED(pstrName); // unused in release builds プログラム初心者のためどこが悪いのかわからず困っています。 原因となるようなミスを教えてください。 よろしくお願いします。

  • ファイルは日時が更新されない?

    自分のPCで作成したデータを、バックアップサーバに保存するときに、あれ?と思ったので質問です。 ・フォルダに、いくつかのファイルが入っている ・フォルダをPCとバックアップサーバに保管し、常に同じファイルが二つ存在するようにする ・フォルダ内にあるひとつのファイルを修正→ファイルの更新日時が反映 ・フォルダの日時は、中のファイルが更新されているのに、ファイル作成時のまま フォルダごと更新するときに、フォルダの更新日時が中のファイルを更新するたびに連動すれば、どちらが新しい最新のデータかわかるのに、なぜ、フォルダの日時は作成時のままなんでしょうか。 バックアップを取る際に、毎日やっていれば問題ないですが、たくさんのファイルを管理している中で、いちいちフォルダの中をあけてファイルの更新日時を比較するのは面倒です。 みなさん、どのように対応していらっしゃいますか?

専門家に質問してみよう