VS2013关于lambda和局部类共用产生的问题
2017-06-07 16:57
225 查看
注意以下 ConstructFromCommandLine函数中 ProcessInformation 结构和 pi 变量构造时传递的 lambda表达式,以及lambda表达式的捕获列表中的&sResult和return sResult;语句。这些代码组合导致VS2013编译出一段神奇的结果。
若在ResumeThread失败后(为了测试在 if 中增加了 || 1 )向 sResult 中写入错误描述字符串,然后执行 return sResult返回,但在真正返回前会先析构 pi 对象,而析构 pi 对象时又会调用一个lambda表达式向 sResult 中追加内容。所以,sResult的内容应该是 ResumeThread失败后写入的字符串和 pi 的析构函数中调用lambda表达式写入的字符串这两部分。
而实际用VS2013测试的结果是,sResult只包含了ResumeThread失败后写入的部分,不包括 pi 析构函数中写入的。
下图是VS2013生成的汇编代码:
以我的理解,应该对调01556F57(构造用于返回的新String对象)和01556F81(调和pi的析构函数)两个地址处代码才正确。但为何编译器会编译出这样的结果?还望高人解惑。
现在暂只记下不能这样做……
String CDebugger::ConstructFromCommandLine( __in LPCTSTR lpCommandLine ) { /* 析构时会调用 TerminateProcess终止 hProcess的类。*/ struct ProcessInformation : public PROCESS_INFORMATION { ProcessInformation( function< VOID( PROCESS_INFORMATION & )> pfnErrorNotify ) : pfnTerminateFailedNotify( pfnErrorNotify ) { ZeroMemory( static_cast<LPPROCESS_INFORMATION>(this), sizeof( PROCESS_INFORMATION ) ); } ~ProcessInformation() { if( hThread != NULL ) ENSURE( CloseHandle( hThread ) ); if( hProcess != NULL ) { if( !TerminateProcess( hProcess, ERROR_SUCCESS ) && WaitForSingleObject( hProcess, IGNORE ) != WAIT_OBJECT_0 || 1 ) pfnTerminateFailedNotify( *this ); ENSURE( CloseHandle( hProcess ) ); } } function< VOID( PROCESS_INFORMATION &) > pfnTerminateFailedNotify; }; String sResult; ProcessInformation pi( [&sResult, this, lpCommandLine]( PROCESS_INFORMATION &pi )->VOID { CONST DWORD dwErrno( GetLastError() ); if( dwErrno != ERROR_SUCCESS ) { sResult.AppendFormat( _T( "\r\n错误代码:0x%08x\r\n描述:%s\r\n" ), dwErrno, (LPCTSTR)String::FormatMessage( dwErrno ) ); } sResult.AppendFormat( _T( "\r\n使用 “%s” 命令行启动 %s(%d) 进程成功," ) \ _T( "但调试器附加失败后未能终止创建的进程,请尝试手动终止该进程;" ), lpCommandLine, PathFindFileName( (LPCTSTR)m_sDebugTargetImagePath ), pi.dwProcessId ); } ); String sCmdLine( lpCommandLine ); STARTUPINFO si{ sizeof( STARTUPINFO ) }; // 启动目标进程 if( !CreateProcess( NULL, sCmdLine.GetBufferReserveLength( sCmdLine.GetLength() + DEFAULT_BUFFER_SIZE ), NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi ) ) { sResult.Format( _T( "使用 “%s” 命令启动进程失败。" ), lpCommandLine ); return move( sResult ); } // 注入抓取器。 sResult = InjectRobberModule( pi.hProcess, (LPCTSTR)m_sRobberModulePathName, TRUE ); if( !sResult.IsEmpty() ){ return sResult; } // 加载调试符号。 if( !LoadSymbol( m_sSymbolsDirectory.IsEmpty() ? NULL : (LPCTSTR)m_sSymbolsDirectory, pi.hProcess ) ) { // 允许加载调试符号失败。但要向stdout输出错误消息。 // VS进程内可通过重写STARTUPINFO中的hStdOutput把输出重定向的VS的输出窗口。 DbgPrint( _T( "从 %s 目录加载调试符号失败。Errno:0x%08x,消息:%s\n" ), m_sSymbolsDirectory.IsEmpty() ? _T( "默认" ) : (LPCTSTR)m_sSymbolsDirectory, GetLastError(), (LPCTSTR)String::FormatMessage(GetLastError() ) ); } if( ResumeThread( pi.hThread ) != 1 || 1) { UnloadRobberModule( pi.hProcess, (LPCTSTR)m_sRobberModulePathName ); sResult.AppendFormat( _T( "使用 “%s” 命令行启动 %s(%d) 进程成功," ) \ _T( "但附加调试模块后未能将其恢复运行,不能继续调试;" ), lpCommandLine, PathFindFileName( (LPCTSTR)m_sDebugTargetImagePath ), pi.dwProcessId ); return sResult; } m_hDebugTargetProcess = pi.hProcess; m_dwDebugTargetProcessId = pi.dwProcessId; m_bHasAttach = TRUE; pi.hProcess = NULL; return NULL_STRING; }
若在ResumeThread失败后(为了测试在 if 中增加了 || 1 )向 sResult 中写入错误描述字符串,然后执行 return sResult返回,但在真正返回前会先析构 pi 对象,而析构 pi 对象时又会调用一个lambda表达式向 sResult 中追加内容。所以,sResult的内容应该是 ResumeThread失败后写入的字符串和 pi 的析构函数中调用lambda表达式写入的字符串这两部分。
而实际用VS2013测试的结果是,sResult只包含了ResumeThread失败后写入的部分,不包括 pi 析构函数中写入的。
下图是VS2013生成的汇编代码:
以我的理解,应该对调01556F57(构造用于返回的新String对象)和01556F81(调和pi的析构函数)两个地址处代码才正确。但为何编译器会编译出这样的结果?还望高人解惑。
现在暂只记下不能这样做……
相关文章推荐
- 关于opencv2.4.9和VS2013在windows7下无法打开摄像头的问题的扯淡解决办法
- 关于VS2013下inet_ntoa函数不能使用的问题
- 关于孙鑫课程第14课网络编程使用VS2013 inet_addr,inet_ntoa出现的问题
- 关于VS编译DevExpress默认产生几个多余的语言包的问题解决
- 关于VS2013无法加载解决方案中项目问题
- 关于VS2013调试时main带命令行参数的问题
- 关于MATLAB2016a与VS2013混编的函数无法解析的问题
- 关于VS2013编辑器的问题
- 关于解决VS2013 community版本卸载后重装不能的问题
- 关于安装vs2015后, vs2013打开项目工程失败崩溃的问题!
- 关于opencv2.4.9和VS2013在windows7下无法打开摄像头的问题的扯
- 关于VS2013 mfc使用Edit control控件显示输出内容问题
- VS2013关于库的两个问题
- 关于VS2013 MFC单文档菜单项设置复选框的出现的问题以及处理方法
- 关于vs2013 mysql Ef框架中提示版本不兼容问题的解决办法
- 关于vs2013创建WINDOWS程序无法使用多字符集的问题
- 关于VS2013 && VS2015的安装问题
- 关于vs2013上面socket连接错误的问题
- 关于VS编译DevExpress默认产生几个多余的语言包的问题解决
- 关于VS2013代码自动折叠的问题