- 締切済み
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と外部関数で使うことは問題があるのでしょうか。教えてください。
- みんなの回答 (6)
- 専門家の回答
みんなの回答
- Oh-Orange
- ベストアンサー率63% (854/1345)
続き。 // ファイルが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" ); } } }
- Oh-Orange
- ベストアンサー率63% (854/1345)
★アドバイス >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)
>2つのファイルが1kBでとまり、それ以降 おそらく1KBも書き込まれていません。。。 1KBというのは恐らくディスク上のサイズに過ぎず、 実際にファイルのプロパティからみれば 数バイト程度書き込まれている程度でしょう。 ハンドルがグローバル変数になっているのですが、 見たところ通信処理などがありそうですが、 スレッドなどは使用していないのでしょうか? >HANDLE_WRITE 上記の関数で失敗しているということでしょうか? とりあえず、GetLastErrorの値を随所に出力するようにし、 何の関数が、どの様なエラーコードで終了しているかを 調べることが重要です。
お礼
そうでした。 2つのファイルともに1KBでとまり、それ以降は何も出来ない状態でした。 スレッドの入ったプログラムにこの処理を入れようとしています。 正常に動くか、まずは小さいものを作ろうと思い、はじめました。 エラーはHANDLE_WRITE関数でおこっていて、ハンドルが無効という6番のエラーでした。 ご指摘ありがとうございました。
- sakusaker7
- ベストアンサー率62% (800/1280)
> ハンドルを閉じなかったのですが、いけないようですね。 解決したのでしょうか? まあそれはおいときまして、コードを見せてくれと言ったのは 実際にAPIを呼び出していたり、ハンドルを渡している部分なんですが(^^;
補足
#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)
>GetSizeFile こんな関数WIN32APIにあったかな。。。? GetFileSize? >HANDLEをexternでmainと外部関数で使うことは問題があるのでしょうか 在ります。 例としては、そのプロセスが複数実行された場合やファイルIOが遅延した場合などに発生します。同じプロセス内でもスレッド内で書き込みを 行っていたりするとなる場合があります。 Globalにハンドルを持つならばしっかり排他制御する必要があります。 オープン状態で書き込みを続ける場合は今回のように2つのファイルを ロテートさせる必要がありますが、ファイル(HANDLE)をきちっと閉じたりしていますか?そうでない場合も今回のようなことが起こりえます。 #もう少し具体的にコードなどがあると良いと思います。。。
お礼
早速のご回答、ありがとうございます。 >こんな関数WIN32APIにあったかな。。。? >GetFileSize? すみません。GetFileSizeです。 >在ります。 >例としては、そのプロセスが複数実行された場合やファイルIOが遅延した場合などに発生します。同じプロセス内でもスレッド内で書き込み>を >行っていたりするとなる場合があります。 >Globalにハンドルを持つならばしっかり排他制御する必要があります。 >オープン状態で書き込みを続ける場合は今回のように2つのファイルを >ロテートさせる必要がありますが、ファイル(HANDLE)をきちっと閉じ>たりしていますか?そうでない場合も今回のようなことが起こりえます。 ファイルを開いた状態で書込みを続けたいのですが、HANDLEをとじてしまうとその値がなくなって、処理のサイズチェックの時に動かなくなってしまっていたのでハンドルを閉じなかったのですが、いけないようですね。
- sakusaker7
- ベストアンサー率62% (800/1280)
CreateFileでファイルを開いたときそのハンドルは正常なもので GetFileSizeとGetFileTimeに対してそのハンドルを 渡したときは正常動作しているということで良いですか? で、 > 書込みのWriteFileは外部関数として私が > 作ったものを呼び出しています。HANDLEのエラーは書込みの際起きているのですが、 > HANDLEをexternでmainと外部関数で使うことは問題があるのでしょうか。教えてください。 API の WriteFileを使わずに書き込みしているということでしょうか? その自作しているというWriteFileでどうやってファイルを書き出しているのか コードを見せてもらえませんか?
お礼
ご回答ありがとうございます。 助かります。 >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; }
お礼
おそくなりました。 本当に本当にありがとうございます!! 解決しました!! とても細かく説明してくださり、大変勉強になりました。 きちんと勉強したいと思います。 ありがとうございました。