未使用函数参数的编译器优化
Compiler optimization on not used function parameters
几天来我在使用 Windows RPC 时遇到了一个奇怪的问题。现在我找到了解决方案,但我想知道什么是防止这个问题的正确方法。
所以基本上我在调用 NdrClientCall2
函数时遇到了问题。正如您在文档中所见,此函数的第三个参数是指向客户端调用堆栈的指针。我将 midl.exe
生成的 C 代码更改为我自己的 C++ 版本,因此我的调用者看起来像这样:
void CppRpc::InternalCommand(int pSize, char buffer[1000000]) const
{
RpcTryExcept
{
NdrClientCall2(PMIDL_STUB_DESC(&m_rpc_stup_description),
PFORMAT_STRING(&MIDL_PROCFORMAT_STRING.Format[0]),
reinterpret_cast<unsigned char *>(&pSize));
}
RpcExcept(1)
{
std::cerr << "Runtime reported exception " << RpcExceptionCode()
<< std::endl;
}
RpcEndExcept
}
在使用完全优化的发布模式下,我遇到了一两天的访问冲突,然后我了解到由于此函数中未使用参数 buffer
,编译器优化将以某种方式删除此参数。
但是我需要将此参数放在堆栈上,以便 NdrClientCall2
可以将其流式传输到服务器。如果我将 buffer
的任何用途(例如 char dummy = buffer[0];
添加到函数伙伴中,那么它将正常工作。
所以我的问题是,如何防止对这种情况进行优化?
我正在使用 visual studio 2017.
我不建议这样做。因为 InternalCommand
是您的内部函数,所以编译器可能会更改其参数的布局。而(据我了解)您需要特定的布局,其中有一个 int
变量,后跟为堆栈保留的缓冲区。
此外,如果您更改函数调用约定(即 cdecl
与 stdcall
),此布局可能会发生变化。
我会用单个 int
字段定义一个结构 (POD),将指向它的指针传递给您的函数,而调用者分配的实际结构有更大的大小。
像这样:
struct StackFrame
{
int pSize;
char pStack[1000000]; // stack goes here
};
// ...
void CppRpc::InternalCommand(StackFrame* pStack) const
{
RpcTryExcept
{
NdrClientCall2(PMIDL_STUB_DESC(&m_rpc_stup_description),
PFORMAT_STRING(&MIDL_PROCFORMAT_STRING.Format[0]),
reinterpret_cast<unsigned char *>(pStack));
}
RpcExcept(1)
{
std::cerr << "Runtime reported exception " << RpcExceptionCode()
<< std::endl;
}
RpcEndExcept
}
几天来我在使用 Windows RPC 时遇到了一个奇怪的问题。现在我找到了解决方案,但我想知道什么是防止这个问题的正确方法。
所以基本上我在调用 NdrClientCall2
函数时遇到了问题。正如您在文档中所见,此函数的第三个参数是指向客户端调用堆栈的指针。我将 midl.exe
生成的 C 代码更改为我自己的 C++ 版本,因此我的调用者看起来像这样:
void CppRpc::InternalCommand(int pSize, char buffer[1000000]) const
{
RpcTryExcept
{
NdrClientCall2(PMIDL_STUB_DESC(&m_rpc_stup_description),
PFORMAT_STRING(&MIDL_PROCFORMAT_STRING.Format[0]),
reinterpret_cast<unsigned char *>(&pSize));
}
RpcExcept(1)
{
std::cerr << "Runtime reported exception " << RpcExceptionCode()
<< std::endl;
}
RpcEndExcept
}
在使用完全优化的发布模式下,我遇到了一两天的访问冲突,然后我了解到由于此函数中未使用参数 buffer
,编译器优化将以某种方式删除此参数。
但是我需要将此参数放在堆栈上,以便 NdrClientCall2
可以将其流式传输到服务器。如果我将 buffer
的任何用途(例如 char dummy = buffer[0];
添加到函数伙伴中,那么它将正常工作。
所以我的问题是,如何防止对这种情况进行优化? 我正在使用 visual studio 2017.
我不建议这样做。因为 InternalCommand
是您的内部函数,所以编译器可能会更改其参数的布局。而(据我了解)您需要特定的布局,其中有一个 int
变量,后跟为堆栈保留的缓冲区。
此外,如果您更改函数调用约定(即 cdecl
与 stdcall
),此布局可能会发生变化。
我会用单个 int
字段定义一个结构 (POD),将指向它的指针传递给您的函数,而调用者分配的实际结构有更大的大小。
像这样:
struct StackFrame
{
int pSize;
char pStack[1000000]; // stack goes here
};
// ...
void CppRpc::InternalCommand(StackFrame* pStack) const
{
RpcTryExcept
{
NdrClientCall2(PMIDL_STUB_DESC(&m_rpc_stup_description),
PFORMAT_STRING(&MIDL_PROCFORMAT_STRING.Format[0]),
reinterpret_cast<unsigned char *>(pStack));
}
RpcExcept(1)
{
std::cerr << "Runtime reported exception " << RpcExceptionCode()
<< std::endl;
}
RpcEndExcept
}