• 締切済み

VC++ Exprss:ファイルアクセス拒否

C言語でのプログラミングを行っています。環境はVC++ Express 2010、XPのSP3です。 バイナリファイルへの書き込みで、errno13、Permission deniedが発生します。 循環リストを読み込み/書き込みをするプログラムです。 以下、エラー発生までの流れです。 1. fopen_s "rb"でファイルをオープン。freadで読み込み。 -存在しなければエラーメッセージを表示して入力処理へ。 -存在する場合は、バイナリデータを構造体ポインタへ読み込む。 2. 構造体への入力処理。 3. "wb"でファイルをオープン。リストの先頭から終端までをfwriteで書き込み。 -存在しない場合は、新規作成。 -存在する場合は、ファイル自体を上書き。(上書きを行う時にのみ、errno13のエラーが発生します。) ファイルはデスクトップに作成しています。 情報に不足があるかもしれませんが、これ以上は思いつかなかったので必要な情報があればご指摘をください。コードを載せたかったのですが、行数が多いので流れを書かせていただきました。 ご教授お願いいたします。

みんなの回答

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.6

>確かにそうなんです。でも循環リストを作る時に始めと最後の構造体をHEADとENDとした場合、 >END->NEXT_PTRにはHEADが入っているので無限ループに陥ってしまいます… 循環にする必要があるのかどうかを検討した方がいいんじゃないですかねぇ…。 リスト構造で作ったリングバッファみたいなもんなんでしょうか? 私ならHEADのアドレスを記憶しておいて回しますね。 int COUNTER(list_t *HEAD) {  int COUNT;  list_t *TEMP;  for(COUNT = 0, TEMP = HEAD;TEMP->NEXT_PTR != HEAD;TEMP = TEMP->NEXT_PTR, COUNT++);  return COUNT; } こんな感じですかね。 リスト構造作るときは面倒ですが…双方向リストにしておけばHEADの前がENDになるんじゃないですか? # 関係ありませんが…変数名や関数名を「全て大文字」にするのは個人的にちょっと……。 >どうにか解決しようと調べたりしてるんですが、解決策は特に思いつかず… どういう構造体なのか謎のままなので細かいところは自分で考えて貰うことになりますが…。 構造体の中身だけ書き出し、読み込む時はmalloc()なりでメモリを確保しながら読み込んでリスト構造に追加していく…ってところでしょう。 構造体定義をまるっと書き出すとポインタの問題以外に無駄なデータの書き出しも発生するでしょうしね。 パディングとか、文字列記憶のために固定長の配列があれば'\0'以降のゴミとか。 # うっかりその固定長の領域にパスワードなり記録していたらそれもゴミとして書き出されますよ。 私は固定長のバッファでも文字列長(WORDサイズで書き出しなど)して、その後にそのままベタで書き出し…とかやってますね。 1つのリスト構造の書き出しサイズは一定にならないんでファイル内でシークして…という手は使えなくなりますけど。 # 検索するならどうせメモリにリスト構造で読み込んでから…なのでシークの必要がない。 # どうしてもファイル内でシークが必要ならサイズ情報を拾いながら都度都度シークしていく。 # まぁその場合はリスト構造1つ分のサイズを予め算出して書き出しておきますけどね。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.5

>少し長くなりますが、こちらが正確です・・・ 掲示されている「だけ」の範囲であれば、とりあえず動くこんじゃないですかね。 リスト構造体をまるっとファイルに書き出し&読み込みしているっぽいところは、かな~り怪しいですが…。 # ポインタ変数の内容をファイルに書き出して、次に読み込んだときにそのポインタが有効かはかなりギモン。 あと、リスト構造なら終端はHEAD->NEXT_PTRがNULLになっている。というのが一般的かと思われます。 # まぁどう作ろうと自由ですが。 なお… file(1,~,○○)とfile(2,~,○○)はセットにしないと正常動作しませんな。 file(1,~,○○)のあとにfile(2,~,××)してfile(1,~,○○)だと多重オープンですし。 # まぁ、第3引数で私ファイルポインタが別でも対象になるファイル名は固定みたいなんでどっちみち多重オープンの余地は残されていますな。 printf()デバッグでもしてfile()のコールされている状態確認してみたらどうですか? 私ならファイルのオープンとクローズは一つの関数内に纏めますね。 もちろん読み書きも…ですが。 ファイルをオープンしたまま関数から抜ける。という事態はなるべく避けます。 # 読み書きの実体を関数として切り出すことはありますけどね。長くなったりするときとか。 多重オープンではなくNTFSのファイル権限が変…という可能性もありますかね。 新規作成は可能でファイルの更新は禁止…なんていうアクセス権が設定できたかはちと調べ切れていませんが。 # Linuxとかだと、上位ディレクトリのパーミッションによっては妙な事になることもあったような。 # http://wiki.bit-hive.com/north/pg/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8%A5%EA%A4%CE%A5%D1%A1%BC%A5%DF%A5%C3%A5%B7%A5%E7%A5%F3 # -wで読み書きは可能だけど新規作成や削除は不可…ですな。 Windowsでそれが可能かは不明。

lsp139
質問者

補足

wormholeさんもおっしゃっているとおり、リスト構造自体をバイナリデータに書き出している部分は、正常動作しません。どうにか解決しようと調べたりしてるんですが、解決策は特に思いつかず… >あと、リスト構造なら終端はHEAD->NEXT_PTRがNULLになっている。というのが一般的かと思われます。 確かにそうなんです。でも循環リストを作る時に始めと最後の構造体をHEADとENDとした場合、 END->NEXT_PTRにはHEADが入っているので無限ループに陥ってしまいます… breakしようかとも思ったのですが、ループ中のHEADポインタがENDを指すタイミングを確実に判断できず… とりあえずはchar型のポインタを利用して、END構造体の場合のみNULLを代入することでそれを終了条件としています。 >printf()デバッグでもしてfile()のコールされている状態確認してみたらどうですか? やってみます。 >私ならファイルのオープンとクローズは一つの関数内に纏めますね。 >もちろん読み書きも…ですが。 >ファイルをオープンしたまま関数から抜ける。という事態はなるべく避けます。 オープンとクローズをまとめることにします。 ファイル権限は大丈夫でした。 ありがとうございました。

  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.4

#3の補足を読む限りいろいろ問題ありそうです。 ポインタ値をそのままファイルに書き込み、読み込み時にもそのまま使用してるようですし(シリアライズ、デシリアライズがされてない)。 読み込み処理がされた場合の読み込まれたポインタ値はあてになりませんので、「さまざまな処理」とコメントされてる部分もまともに動作してない可能性が高いです(というよりほぼ100%してないと思う)。 あと余計な突っ込みになりますがfile()関数で読み込みオープン、書き込みオープン、クローズをすべて行わせることで可読性が落ちてると思います。マジックナンバーも使われてますし。

lsp139
質問者

補足

>ポインタ値をそのままファイルに書き込み、読み込み時にもそのまま使用してるようですし >(シリアライズ、デシリアライズがされてない)。 >読み込み処理がされた場合の読み込まれたポインタ値はあてになりませんので、 >「さまざまな処理」とコメントされてる部分もまともに動作してない可能性が高いです >(というよりほぼ100%してないと思う)。 おっしゃる通りです。 シリアライズ、デシリアライズの概念?と実装方法について勉強しようと思い、サイトをいろいろ見て回りましたが、C++向けの解説サイトが多くC向けのものがありません。 以下のサイトはC++ですが、Cでの実装方法を学ぶのに問題ありませんでしょうか? http://omt.sourceforge.jp/serializer.html C++の知識、オブジェクト指向概念の知識は皆無に等しいです。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.3

既に指摘されてますが… if文中でfopen_s()でオープン試みて成功した場合に二重にオープンしようとしてますね。 共有モードが排他であれば「既にオープン済み」ってコトで2回目のfopen_s()はエラーになるでしょう。 共有モードを正しく設定する必要があります。 『どうしても多重オープンする必要がある』のであれば…ですが。 そして、先にオープンしたハンドルはめでたくリソースリークです。 # プロセスが終了したときにOSが回収してくれるとは思われますが…。お行儀いいとは言えないですかねぇ…。 ところで…… >//エラーメッセージ >printf("OPEN ERR. - %d\n ERR^Msg: %s\n",error,strerror(error)); >fclose(DATA); と >printf("MAKE FILE, Please. Err- %d\nERR^Msg: %s\n",error,strerror(error)); >Sleep(0); >fclose(DATA); は正しく通過できるんですか? 手元のVC++2010EEでは前者(のfclose())がNULLポインタで怒られましたけど。

lsp139
質問者

補足

少し長くなりますが、こちらが正確です・・・ ///BOOLEAN #define FALSE 1 #define FALSE_ALLOC 2 #define TRUE 0 ///File Name #define __FILENAME__ "G:\\Documents and Settings\\アカウント名\\デスクトップ\\DATA.u" int file(const int mode_OpCl, char const *mode_WR, FILE **DATA){ errno_t error; if (mode_OpCl == 1){ if(strcmp(mode_WR,"_READ") == 0) { if((error=fopen_s(DATA,__FILENAME__,"rb")) != 0) { printf("\t***** Cannot Open FILE ****\n\t* File OPEN ERR. - %d *\n\t* ERR^Msg: %s *\n\t*****************************\n",error,strerror(error)); Sleep(0); //Make Sound return FALSE; } } else if(strcmp(mode_WR, "_WRITE") == 0) { if((error=fopen_s(DATA,__FILENAME__,"wb")) != 0) { printf("MAKE FILE, Please.Err- %d\nERR^Msg: %s\n",error,strerror(error)); Sleep(0); //Make Sound return FALSE; } } } else if (mode_OpCl == 2) { fclose(*DATA); } else{puts("ERROR argument.");} return TRUE; } extern int WRITE_DATA(list_t *POS_HEAD, int W_COUNTER, FILE *fp){ if(fwrite(POS_HEAD, sizeof(list_t), W_COUNTER, fp) ==W_COUNTER) { puts("Cannot Write."); return FALSE; } return TRUE; } extern int READ_DATA(list_t *LIST, int R_COUNTER, FILE *fp){ if(fread(LIST, sizeof(list_t), R_COUNTER, fp) ==R_COUNTER) { puts("Cannot Read."); return FALSE; } return TRUE; } extern int COUNTER(list_t *HEAD){ int COUNT = 0; while(HEAD->STATUS != NULL) ///構造体の数を数えます { ++COUNT; HEAD = HEAD->NEXT_PTR; } return COUNT; } int main(void){ puts("\nReading......\n"); if((file(1, "_READ", &DATA)) == FALSE) { printf("There is NO DATA FILE. But if you said...\n\t1. I have made DATA FILE yet, move the file in this directory.\n\t"); printf("2.I have not made DATA FILE, Please Make the file .\n"); } READ_DATA(R_LIST, amount, DATA); file(2, NULL,&DATA); /* さまざまな処理。 */ //書き込み file(1, "_WRITE", &DATA); //ここでエラーが起こり、停止します。「MAKE FILE, Please.Err- 13 ERR^Msg: Permission denied」 count = COUNTER(HEAD); WRITE_DATA(HEAD, count+1, DATA); //先頭から書き込む(読み込んだデータも処理済) file(2, NULL,&DATA); }

  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.2

>/*書き込み*/ >//ファイルが存在しなかったしなかった場合 >if((error=fopen_s(&DATA,上述のディレクトリ,"wb")) != 0) >{ fopen_sが成功した場合、それをfcloseせずにfopen_sしてるようですが。 そもそもfopen_sしなおす必要ありますか? 読み込み時も同様。 また >//既存ファイルから読み込んだ構造体の数をCOUNTERに代入 >fread(読み込み用の構造体ポインタ, sizeof(構造体サイズ), COUNTER, DATA); はCOUNTERに代入などされませんよ。

  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.1

1 の読み込み処理後にクローズせずに、3で上書きしようとしてるとかでは? こういう場合は、流れを書かれるのではなく処理を簡略化して同様のエラーが出るコードを書かれた方がいいです。流れを書いたつもりでも実際のコードはそうなってないという事もありますから。

lsp139
質問者

お礼

間違いがありましたので、こちらを・・・すみません。 ------------------------------------ FILE *DATA; errno_t error; /*読み込み*/ //ファイルが存在しなかった場合 if((error=fopen_s(&DATA,"G:\\Documents and Settings\\アカウント名\\デスクトップ¥\DATA.unm","rb")) != 0) { //エラーメッセージ printf("OPEN ERR. - %d\n ERR^Msg: %s\n",error,strerror(error)); fclose(DATA); } //ファイルが存在する場合 else { fopen_s(&DATA,"上述のディレクトリ","rb") //既存ファイルから読み込んだ構造体の数をCOUNTERに代入 fread(読み込み用の構造体ポインタ, sizeof(構造体サイズ), COUNTER, DATA); fclose(DATA); } /* 以降構造体の作成、検索、削除などの処理。 */ /*書き込み*/ //ファイルが存在しなかったしなかった場合 if((error=fopen_s(&DATA,上述のディレクトリ,"wb")) != 0) { printf("MAKE FILE, Please. Err- %d\nERR^Msg: %s\n",error,strerror(error)); Sleep(0); fclose(DATA); } else { fopen_s(&DATA,上述のディレクトリ,"wb"); //ここでエラーが起こる。 //ここまでに作成した構造体リストの数をカウントしてint型変数countに代入 fwrite(HEAD, sizeof(構造体のサイズ), count, DATA); fclose(DATA); } -----------------------------

lsp139
質問者

補足

コードが2000行近くあって、関数もたくさんあるので簡略化の仕方がわからずこうなってしまいました・・・ ファイル処理の流れはこの二つです。 ------------------------------------ FILE *DATA; errno_t error; /*読み込み*/ //ファイルが存在しなかった場合 if((error=fopen_s(&DATA,"G:\\Documents and Settings\\アカウント名\\デスクトップ¥\DATA.unm","rb")) != 0) { //エラーメッセージ printf("OPEN ERR. - %d\n ERR^Msg: %s\n",error,strerror(error));       fclose(DATA); } //ファイルが存在する場合 else { //既存ファイルから読み込んだ構造体の数をCOUNTERに代入 fread(読み込み用の構造体ポインタ, sizeof(構造体サイズ), COUNTER, DATA); fclose(DATA); } /* 以降構造体の作成、検索、削除などの処理。 */ /*書き込み*/ //ファイルが存在しなかったしなかった場合 if((error=fopen_s(&DATA,上述のディレクトリ,"wb")) != 0) { printf("MAKE FILE, Please. Err- %d\nERR^Msg: %s\n",error,strerror(error)); Sleep(0);       fclose(DATA); } //ここでエラーがでて停止する else { //ここまでに作成した構造体リストの数をカウントしてint型変数countに代入 fwrite(HEAD, sizeof(構造体のサイズ), count, DATA); fclose(DATA); } ----------------------------- これでなんとかお願いできますでしょうか・・・

関連するQ&A

  • バイナリーとして.wavファイルに書き込む方法は?

    バイナリーで書き込み拡張子.wavのファイルにしたいと考えています。 なお、.wavファイルのデータ構造は分かっています。 この場合、fwriteでバイナリーファイルとして書き込み、 拡張子を.wavにすればよいのでしょうか? それとも、.wavファイルとして書き込むためになんらかの処理が必要なのでしょうか? (おそらく拡張子を変えるだけだと、.txtファイルになると思いますので。)

  • SQLServerが存在しないか、アクセスが拒否されました

    WindowsXP(SP2) SQLServer2000(SP4) VisualBasic6.0(SP6) の環境で開発しています。 数千件の画像のファイル名称(パスを含む)をテーブルに登録する操作を行うアプリがあります。この処理を実行中に、下記のエラーが発生します。 "[DBNETLIB]{ConnectionOpen(Connect()).]SQL Serverが存在しないか、アクセスが拒否されました" 1レコード目の操作から発生するのならまだしも、1000件くらいINSERT処理が進んでから発生するので、原因が分かりません。 また、エラーが発生するのは固定の環境だけで、同じアプリ、同じDB、同じ画像ファイルを使っても、別の環境では発生しません。 こんな場合、どの辺を確認したら良いかご教授下さい。 宜しくお願いします。

  • 音声ファイルの転送がうまくいきません

    音声ファイルの転送がうまくいきません。 ビルダー7ですが、「転送中にエラーが発生しました。(errno=550)」とでるのです。 ファイルの容量がおおきすぎるからではないかと思うのですがこういう場合どうすればいいでしょうか?

  • EXCEL VBAでIEアクセスを行なうとアクセスが拒否されましたとなる

    状況説明 EXCELのVBAで、EXCELのセルデータをWEBの入力フィールドへ書き込む処理を行ないたく奮闘中です。 ここで、おもわぬエラーに遭遇して困っていますのでお助けください 通常のページに書き込むときは、問題なく処理できるのに、フレーム構造のページに書き込もうとすると、「アクセスが拒否されました」とのエラーが返されて処理が実行できません。ググッて見たのですが、セキュリティ上の問題との回答が見受けられるのですが、実際問題としてフレーム構造のページへの書き込みは不可能なのでしょうか? ぜひ知恵をお貸しください、よろしくお願いします

  • VC++でファイルが開けないんです

    以下のようなプログラムを作っています。 実行内容としては、 MessageBoxでYesNo選択 ↓ Yesなら~~という処理、 Noなら、ファイルの選択画面を立ち上げて、ファイルを選択。ReStartという関数にそのファイル名を渡す ↓ そのあと、現在時間を取得して、filename4というファイルに追加書き込みをする。 という処理です。 ここで、私はfilename4=./time/AAA.timeと指定しているのですが、 Yes処理のあとはうまくfileが開けて書き込めるのですが、No処理のあとはfileが開けないんです。 おそらくは、No処理の中のファイル選択で、VC++のプロジェクトがあるディレクトリと違うディレクトリから選択しているせいだと思うんですが、これを解消する方法はありますでしょうか?? VC++短いんで、もし単純でしたら申し訳ないですが、どうぞよろしくお願いします。 ------------------------------------------- ・・・ if(MessageBox("はじめから?", "message", MB_YESNO)==IDYES){ ~~} else{ CFileDialog fd(TRUE,"","",OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_LONGNAMES, "位置ファイル (*.POSI)|*.POSI|" "全てのファイル(*.*)|*.*||", NULL); if(fd.DoModal()==IDOK){ posifilename = fd.GetPathName(); } ReStart(posifilename); } stream4 = fopen(filename4,"a"); if(stream4 == NULL ){ MessageBox("Cannot Open the File!!", "error", MB_OK); } strwork4.Format("%ld,",time(NULL)); fprintf(stream4,strwork4); fclose(stream4);

  • 【VC++2005(CLR)】ファイル書き込み時、他でファイルが開かれていると落ちる

    いつも大変お世話になっています。 VC初心者です。 現在、ファイル書き込み処理で悩んでいます。 他のユーザがファイルをオープンしてたり、開こうとすると 落ちてしまいます。 たとえば、ファイルが開かれていることを検知して、 ユーザに「ファイルを閉じてください」とメッセージを出した後、 再度書き込み処理を実行できませんでしょうか。 (書き込み中は他のユーザからのアクセスを拒否させたいです。) 現在以下のようなソースを書いています。 //ファイルオープン System::IO::StreamWriter^ sw = gcnewSystem::IO::StreamWriter( path_w,false,System::Text::Encoding::Default); //ファイル書き込み String^ newData = "aaa"; sw->WriteLine(newData); //ファイルクローズ sw->Close(); お手数ですが、よろしくお願いします。

  • VC++2003でSDIのMFCアプリ作成中です。

    アイコン上にファイルをドロップし、ファイルをオープンする動作を実装し、 正常系は動作確認できました。 しかし、ファイルに読み込み制限などをかけていた場合、こちらのエラー処理に入る前に Windows内部エラー処理に入ってしまうようで、「○○へのアクセスは拒否されました」と ダイアログが表示されます。 デバッグで見て云ったところ、ProcessShellCommand(cmdInfo)の内部でエラーが発生し、 強制的におちているようですが、具体的にどこのクラス、メソッドでエラーを受け取って いるのでしょうか? オーバーライドしてエラー処理を自分で実装したいと考えています。

  • vs2010 VC++ Open 記述方法

    VS2010のVC++でバイナリデータをOpenしたいのですが、まったくコンパイルが通りません。 ヘルプで見ながら同じように作っているつもりですが、出来ませんでした。 エラーは・・・CFile::Openのインスタンスが引数リストと一致しませんと出てしまいます。 記述はこんな感じです! #include <afx.h> CFile fr; CFileException e; char* pFileName = "Kaltr.bat"; if(!fr.Open( pFileName, CFile::modeRead | CFile::typeBinary, &e)){   -/-/-/ 処理 -/-/-/ } 参考になるサイトがあったら教えて下さい。 よろしくお願いします。

  • ソケットプログラミングによるファイル送信について

    VC++.NETを利用して、Winsockにてファイル送信プログラムを作成しています。ソケットはUDPを使用しています。 [行いたいこと] A→B端末へ、1024Byteずつバイナリデータ(画像)を送信。 [現在行っていること(A端末側のプログラムの概略)] 1.ファイルオープン 2.fread関数にてバイナリデータの入力(whileにてループ) 3.A→Bへパケットを1024Byteずつ送信。 #define DATA_SIZE 1024 main{ int n; char send_Buf[DATA_SIZE + 1]; if((fp = fopen(fname,"rb+")) == NULL){ printf("ファイルエラー\n"); exit(1); } //nが0でなくなったら、ループを抜ける。 while((n = fread(send_Buf,1,DATA_SIZE,fp)) != 0) { sendto(s, send_Buf, n, 0, (LPSOCKADDR)&addrin, sizeof(addrin)); } } A側でビルドはできますがエラーが発生して実行できません。 よろしければ教えていただけないでしょうか。C言語の基礎もきちんと出来ていないからなのかもしれません・・・>< よろしくお願いします。

  • ファイルへ書込み

    こんにちわ。 ■質問1 ファイルへの書込み(書替え)をどうやってやればいいか悩んでいます。 既に存在する aaa.txt という名前のファイルがあるとします。 aaa.txtをファイルオープンし、ある文字列をキーに検索し、 値を書替えたいのです。 以下の例の様にaaa.txtに、書かれているとします。 例)aaa.txtファイルの中身 LOOP_CNT1=50 LOOP_CNT2=100 LOOP_CNT3=200 LOOP_CNT4=300 LOOP_CNT5=400 "LOOP_CNT3"という文字列をキーに、ファイルから対象文字列を検索し、設定値の 200 を 10000 に書き換えたいのです。 書き換える値、10000 はパラメータから取得します。 書き換えれる場合、それ以降の文字列の値が 上書かれてしまったり、領域を壊してしまったりはしないでしょうか? いい方法があったら教えてください! ■質問2 新規でオープンしたファイルに、 DBからループ処理で取得した値を書き込む処理を行うとします。 ※データは何件あるか分からず、なくなるまで処理します。 エラーが起きた場合のみ、ファイル書込み処理を行っていても 最終的には何も書かれていない0バイトファイルを作成したいのですが どのようにやればいいでしょうか? ※一時的にテンポラリ領域に、格納してエラーがなかった場合のみ ファイルへ書込む場合、テンポラリはどのような持ち方をすれいいで しょうか? テンポラリ用にchar型の変数を用意? データが何件あるか分からないので、 変数のサイズはどのように宣言すればいいですか? そもそも考え方が間違っていますか?

専門家に質問してみよう