سؤال

I'm writing an Windows phone application with C++/CX. The function tries to copy input array to output array asynchronously:

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;
    });
}

This function compiles but cannot run correctly and produces an "Access violation exception". How can I modify values in the output array?

هل كانت مفيدة؟

المحلول

This is Undefined Behaviour: by the time you use your 3 captured (by reference) variables inputData/outputData/byteCount in the lambda, you already returned from CopyAsync and the stack has been trashed.

It's really the same issue as if you returned a reference to a local variable from a function (which we know is evil), except that here the references are hidden inside the lambda so it's a bit harder to see at first glance.


If you are sure that input and output won't change and will still be reachable between the moment you call CopyAsync and the moment you run the asynchronous action, you can capture your variables by value instead of by reference:

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

Since they're only pointers (and an int), you won't be copying the pointed-to data, only the pointers themselves.


Or you could just capture input and output by value: since they're garbage-collected pointers this will at least make sure the objects are still reachable by the time you run the lambda:

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

I for one prefer this second solution, it provides more guarantees (namely, object reachability) than the first one.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top