0

我正在用 C++/CX 编写一个 Windows 手机应用程序。该函数尝试将输入数组异步复制到输出数组:

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在 lambda 中使用 3 个捕获(通过引用)变量时,您已经从中返回CopyAsync并且堆栈已被丢弃。

这实际上与您从函数返回对局部变量的引用(我们知道这是邪恶的)相同的问题,只是这里的引用隐藏在 lambda 中,因此乍一看有点难以看到。


如果您确定并且不会更改并且在您调用和运行异步操作之间仍然可以访问input,您可以通过值而不是通过引用来捕获变量:outputCopyAsync

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

由于它们只是指针(和一个int),因此您不会复制指向的数据,而只会复制指针本身。


或者你可以只捕获inputoutput按值:因为它们是垃圾收集的指针,这至少可以确保在你运行 lambda 时对象仍然可以访问:

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

我更喜欢第二种解决方案,它提供了比第一种解决方案更多的保证(即对象可达性)。

于 2013-08-24T16:02:30.810 回答