2

以下のコードには 2 つの問題があります。まず、1784 エラー コードへの回答を求めて、このフォーラムや他のさまざまなフォーラムを精査してきましたが、試したことはすべて失敗しました。stackoverflow で確認した 2 つのスレッドは、エラー 1784 を返す WriteFileBlockWrite I/O Error 1784です。このフォーラムで他の人をチェックしましたが、今のところ正確には覚えていません。

構造体の配列を空のバイナリ ファイルに保存しようとしています。最初の問題は、サイズ変数 (nNumberOfBytesToWrite パラメーター) が約 99000 バイト未満の場合にアクセス違反が発生することです。その数は飛び跳ねます。しばらくテストしていたとき、99,999 バイトで 100,000 バイトではない場合、アクセス違反が発生しました。もちろん、最終的にやりたいことは、サイズを配列全体のサイズに設定することです。さまざまなサイズでテストできるように、処理する元のコードはコメント アウトされています。

2 番目に発生すること (アクセス違反が発生しない場合) は、エラー コード 1784 が表示され、WriteFile が毎回失敗することです。このトピックに関する他のスレッドが述べているように、これは MSDN で ERROR_INVALID_USER_BUFFER として定義されており、説明は「指定されたユーザー バッファーは、要求された操作に対して有効ではありません」です。このようなファイルを開くためのMSDN独自の例(http://msdn.microsoft.com/en-us/library/windows/desktop/bb540534%28v=vs.85%29.aspx)を見て、いくつか試しましたコードに基づいたバリエーションがありますが、何も機能していないようです。

この問題はおそらく非常に初心者であり、ばかげて単純なものを見落としていると確信していますが、誰かが提案を持っていれば、彼らは大歓迎です。

case IDM_SAVE1:
{
    HANDLE hFile = CreateFile("MineSave.mss", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    int test_buffer[] = {1,2,3,4,5,6,7,8,9,10};

    if(hFile != INVALID_HANDLE_VALUE)
    {
        BOOL bSuccess;
        DWORD size = 100000; //DWORD size = (((sizeof(tile)) * tiles_total));
        LPDWORD bytes_written = 0;
        bSuccess = WriteFile(hFile, test_buffer, size, bytes_written, NULL);
        if(bSuccess)
        {
            MessageBox(hwnd, "File saved successfully.", "Great Job!", MB_OK);
        }
        else
        {
            DWORD error = GetLastError();
            MessageBox(hwnd, "Could not write to file.", "Error", MB_OK);
        }

        CloseHandle(hFile);
    }
    else
    {
        MessageBox(hwnd, "Could not create file.", "Error", MB_OK);
    }
}
break;
4

2 に答える 2

7

バッファーのサイズは 10 int で、Windows では 40 バイトです。そのバッファから 100,000 バイトを書き込もうとしています。これは未定義の動作であり、バッファ オーバーランです。したがって、アクセス違反です。

より大きい値sizeof(test_buffer)、つまり40nNumberOfBytesToWriteパラメータにを渡してはなりませんWriteFile

必要なだけ書き込むまで、一度に 40 バイトを書き込むループでこのファイルを書き込む必要があります。おそらく次のようなものです:

BOOL bSuccess = TRUE;
DWORD bytesRemaining = 100000;
while (bSuccess && bytesRemaining>0)
{
    DWORD bytesToWrite = std::min(sizeof(test_buffer), bytesRemaining);
    DWORD bytesWritten;
    bSuccess = WriteFile(hFile, test_buffer, bytesToWrite, &bytesWritten, NULL);
    bytesRemaining -= bytesToWrite;
}
if (!bSuccess)
{
    //handle error;
}

一度に 40 バイトを書き込むのはかなり遅いです。を呼び出すたびに数 KB 書き込む方が効率的WriteFileです。

ここで行っているように、にも渡す場合NULLは、パラメーターに渡すことはできないことに注意してください。ドキュメントから:lpNumberOfBytesWrittenNULLlpOverlapped

lpNumberOfBytesWritten [アウト、オプション]

……

このパラメーターは、lpOverlapped パラメーターが NULL でない場合にのみ NULL にすることができます。

于 2012-09-28T16:29:34.810 に答える
1

パラメータが非 NULL であるか、パラメータが非 NULL である必要あります。lpNumberOfBytesWrittenlpOverlapped

両方に NULL を渡していますが、これは違法であり、アクセス違反を引き起こします。

于 2012-09-28T16:59:23.780 に答える