0

C++/CX を使用して Windows phone アプリケーションを作成しています。この関数は、入力配列を出力配列に非同期的にコピーしようとします。

IAsyncAction CopyAsync(const Platform::Array<byte, 1>^ input, Platform::WriteOnlyArray<byte, 1>^ output) 
{
    byte *inputData = input->Data;
    byte *outputData = output->Data;
    int byteCount = input->Length;
    // if I put it here, there is no error
    //memcpy_s(outputData, byteCount, inputData, byteCount);
    return concurrency::create_async([&]() -> void {
        memcpy_s(outputData, byteCount, inputData, byteCount); // access violation exception
        return;
    });
}

この関数はコンパイルされますが、正しく実行できず、「アクセス違反の例外」が発生します。出力配列の値を変更するにはどうすればよいですか?

4

1 に答える 1

1

これは未定義の動作です。inputData/outputData/byteCountラムダで (参照によって) キャプチャされた 3 つの変数を使用するまでに、既に戻りCopyAsync、スタックは破棄されています。

これは、関数からローカル変数への参照を返す場合と同じ問題です (これは悪であることがわかっています)。ただし、ここでは参照がラムダ内に隠されているため、一見するとわかりにくい点が異なります。


が変更されず、呼び出した瞬間から非同期アクションを実行する瞬間まで到達可能であることが確実な場合は、参照ではなく値で変数をキャプチャできます。inputoutputCopyAsync

return concurrency::create_async([=]() -> void {
//                                ^ here
    memcpy_s(outputData, byteCount, inputData, byteCount);
    return;
});

それらは単なるポインター (およびint) であるため、ポイント先のデータはコピーせず、ポインター自体のみをコピーします。


inputまたは、値によってキャプチャすることもできoutputます。これらはガベージコレクションされたポインターであるため、ラムダを実行するまでにオブジェクトがまだ到達可能であることを少なくとも確認します。

return concurrency::create_async([=]() -> void {
    memcpy_s(output->Data, input->Length, input->Data, input->Length);
    return;
});

私はこの 2 番目のソリューションを好みます。最初のソリューションよりも多くの保証 (つまり、オブジェクトの到達可能性) を提供します。

于 2013-08-24T16:02:30.810 に答える