0

エラーメッセージは次のとおりです。「0x7c810eac」の命令が「0x00000000」のメモリを参照しました。メモリを「書き込む」ことができませんでした。

デストラクタを削除すれば、すべて問題ありません。しかし、私はここで何が起こっているのか理解していません。どこでもハンドルを閉じる必要があると読んでいますが、ここのコードでは許可されません。(はい、手動で実行できることはわかっていますが、これはクライアントコードの不要な行であり、オブジェクトで処理する必要があると思います。)

#include <windows.h>
#include <iostream>
#include <string>

struct fileHandle {
  HANDLE hFile;
  fileHandle(std::string path) {
    hFile = CreateFile(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_ARCHIVE, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
      printf("error: INVALID_HANDLE_VALUE");
    }
  }
  ~fileHandle() {
    CloseHandle(hFile);
  }
  void save(std::string data) {
    if (!WriteFile(hFile, data.c_str(), data.size(), NULL, NULL)) {
      printf("WriteFile failed: ", GetLastError());
    }
  }
};

int main() {
  fileHandle my_handle("test_file.txt");
  my_handle.save("some text");
}

更新:これは、ファイルが存在しない場合に発生します。ファイルが存在する場合、プログラムの印刷エラーが発生しますが、これは意図されたものです。私はここで、ファイルが作成されるときにこのケースのみをカバーするように求めています(既存のファイルをカバーするようにハンドル作成を書き直す方法を知っています)。

コンパイラ:http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.7.2/32-bit/threads-posix/sjlj/x32-4.7.2-release-posix-sjlj-rev7。 7z

更新2:このコードが機能してファイルに書き込むことについては触れませんでした。メモリエラーは最後にトリガーされます。

4

7 に答える 7

3

すべてのコードを-Wallでコンパイルしてください。時間を大幅に節約します。

printf無効なフォーマット文字列を持つコード内。の正しい解決策は次のようになります( %luprintfに注意してください):

void save(std::string data) {
  if (!WriteFile(hFile, data.c_str(), data.size(), NULL, NULL)) {
    printf("WriteFile failed: %lu", GetLastError());
  }
}

でコンパイルした-Wall場合、コードは次の警告を出します。

filehandle.cpp: In member function 'void fileHandle::save(std::string)':
filehandle.cpp:18:50: warning: too many arguments for format [-Wformat-extra-args]

stderrまた、バッファリングされていないため、エラーをに出力する必要があります。printfバッファを使用しているため、出力が得られませんでした。\nまた、エラーの後にを追加することをお勧めします。

コードを改善するために他の回答も読んでください。三つのルールを使用します。


コメントを読んだ後、私はこれが実際にセグメンテーション違反の理由ではないことに気づきました。(また、Ron Burkのソリューションを見て、何がうまくいかなかったかを確認してください。)

Windows APIのドキュメントによると、lpNumberOfBytesWrittenパラメータはそうでないNULL場合にのみ使用できます。lpOverlapped parameterNULL

したがって、WriteFileが実際に読み取ったバイト数を格納できるDWORDへのポインタを指定する必要があります。最終的な保存は次のようになります。

void save(std::string data) {
  DWORD writtenBytes;
  if (!WriteFile(hFile, data.c_str(), data.size(), &writtenBytes, NULL)) {
    printf("WriteFile failed: %lu", GetLastError());
  }
}

ファイルが存在する場合、INVALID_HANDLE_VALUEをWriteFileに渡すと、ポインタを使用するよりも早くWriteFileが返されるように見えるため、エラーはポップアップしません。

于 2013-02-10T22:29:58.433 に答える
3

WriteFile()の引数が間違っています。最後から2番目の引数をNULLにすることはできません。0に設定したDWORDのアドレスに変更すると、すべてが機能します。書き込まれたバイト数を書き戻そうとしたため、WriteFile()のカーネルで停止していました。

于 2013-02-10T23:18:34.270 に答える
3

CloseHandleのドキュメントには、これが発生する理由が明確になっています。

アプリケーションがデバッガーで実行されている場合、無効なハンドル値または疑似ハンドル値のいずれかを受け取った場合、関数は例外をスローします。

したがって、CreateFileの呼び出しが失敗すると、その後のCloseHandleの呼び出しでSEH例外が発生します。

解決策は、CreateFileの呼び出しが成功した場合にのみ、コードがCloseHandleを呼び出す必要があることです。

他の人が指摘しているように、WriteFileの使用は間違っています。ここでは詳細を繰り返しません。

于 2013-02-11T07:43:04.793 に答える
0
~fileHandle() {
    if(hFile != INVALID_HANDLE_VALUE)
        CloseHandle(hFile);
  }
于 2013-02-10T22:14:12.257 に答える
0

あなたは三つのルールに従っていません-そのため、コンパイラによって生成されたコピーコンストラクタとコピー代入演算子が浅いため、のhFileコピー間で所有権が共有されます。fileHandle

例えば:

fileHandle my_handle("test_file.txt");
fileHandle my_second_handle = my_handle;

これらのどれが実際に破壊のハンドルを閉じる必要がありますか?最初?2番目のものがスコープ外になり、デストラクタを呼び出すとどうなりますか?

この場合、コピーや割り当てを禁止するか、所有権を特定する必要があります。

編集:あなたのスニペットでは、問題はおそらくRonによって指摘されたものですが、これは依然として重要なポイントです。

それは私がそれを扱う方法ではありません。ファイルを開けられなかったら、fileHandle存在すべきではないと思います。無効なオブジェクトを持つことのポイントは何ですか?デストラクタでチェックを行うのではなく、コンストラクタで例外をスローして、無効なオブジェクトを許可しないようにします。

fileHandle(std::string path) {
    hFile = CreateFile(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_ARCHIVE, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
       throw std::exception("file not found");
    }
  }
于 2013-02-10T22:14:28.520 に答える
0

ファイルが正しく開かれたことを確認する必要があります。

 if (hFile != INVALID_HANDLE_VALUE) CloseFile(hFile);
于 2013-02-10T22:14:31.613 に答える
0

安全のために、

~fileHandle() 
{

            if (hfile != INVALID_HANDLE_VALUE)
            {
                CloseHandle(hfile);
                hfile = INVALID_HANDLE_VALUE;
            }
}
于 2021-09-13T17:49:21.760 に答える