microsoft / STL

MSVC's implementation of the C++ Standard Library.
Other
9.88k stars 1.45k forks source link

`stacktrace` gives low fidelity on customer PCs #4726

Closed Ulysses1337 closed 2 weeks ago

Ulysses1337 commented 2 weeks ago

On my rig with VS 17.10.1 installed, I get everything I could ask for in stack traces, even in release builds. If I copy my output binary folder to a customer PC and run my program there, it ignores the PDB next to my executable.

I've tried this on a Win10 and a Win11 PC and they behave the same. I reluctantly installed Debugging Tools for Windows on one of them, but it didn't help. How can I get useful info there?

Dev rig:

0> X:\MyApp\MyApp.cpp(342): MyApp!`CMyApp::InitInstance'::`2'::<lambda_1>::operator()+0x54
1> X:\MyApp\MyApp.cpp(347): MyApp!`CMyApp::InitInstance'::`2'::<lambda_1>::<lambda_invoker_cdecl>+0xC
2> X:\vcpkg\buildtrees\opencv4\src\4.6.0-754ca27223.clean\modules\core\src\system.cpp(1230): opencv_core4!cv::error+0xC8
3> X:\vcpkg\buildtrees\opencv4\src\4.6.0-754ca27223.clean\modules\core\src\system.cpp(1255): opencv_core4!cv::error+0x62
4> X:\vcpkg\buildtrees\opencv4\src\4.6.0-754ca27223.clean\modules\core\src\matrix_wrap.cpp(1476): opencv_core4!cv::_OutputArray::create+0x1B44
5> X:\vcpkg\buildtrees\opencv4\src\4.6.0-754ca27223.clean\modules\core\src\matrix_wrap.cpp(1212): opencv_core4!cv::_OutputArray::create+0x24E
6> X:\vcpkg\buildtrees\opencv4\src\4.6.0-754ca27223.clean\modules\calib3d\src\undistort.dispatch.cpp(98): opencv_calib3d4!cv::initUndistortRectifyMap+0x12C
7> X:\MyApp\MyApp.cpp(369): MyApp!CMyApp::InitInstance+0x3C5
8> mfc140u+0x2B2E34
9> D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(288): MyApp!__scrt_common_main_seh+0x106
10> KERNEL32!BaseThreadInitThunk+0x14
11> ntdll!RtlUserThreadStart+0x21

Customer:

0> MyApp!boost::archive::detail::iserializer<boost::archive::xml_wiarchive,MyFoo>::load_object_data+0x19CB4
1> MyApp!boost::archive::detail::iserializer<boost::archive::xml_wiarchive,MyFoo>::load_object_data+0x19F9C
2> opencv_core4!cv::error+0xC8
3> opencv_core4!cv::error+0x62
4> opencv_core4!cv::_OutputArray::create+0x1B44
5> opencv_core4!cv::_OutputArray::create+0x24E
6> opencv_calib3d4!cv::initUndistortRectifyMap+0x12C
7> MyApp!boost::archive::detail::iserializer<boost::archive::xml_wiarchive,MyFoo>::load_object_data+0x18D15
8> mfc140u+0x2B3504
9> MyApp!boost::archive::detail::iserializer<boost::archive::xml_wiarchive,MyBar>::load_object_data+0x3EDB2
10> KERNEL32!BaseThreadInitThunk+0x14
11> ntdll!RtlUserThreadStart+0x21
AlexGuteniev commented 2 weeks ago

Use /PDBALTPATH:%_PDB% to work around this limitation, then you can put .pdb next to .exe. See /PDBALTPATH.

Sorry about having such annoying undocumented limitation.

Ulysses1337 commented 2 weeks ago

That works; many thanks. I'll definitely apply it across the board from now on. Of course I only get full symbol info on my own binary, i.e. it has no effect on separate libraries like OpenCV in the example. This is not an issue for me, and I know there are tools to patch the embedded path, but IMO path stripping begs to be the default.

Quoting relevant parts of the help page to aid future travelers in their search:

Normally, the linker records the location of the .pdb file in the binaries that it produces. You can use this option to provide a different path and file name for the .pdb file.

and

The linker defines the environment variables %_PDB% and %_EXT%. %_PDB% expands to the file name of the actual .pdb file without any path information and %_EXT% is the extension of the generated executable.

AlexGuteniev commented 2 weeks ago

I've contributed the std::stacktrace feature to this STL some time ago, implementing it on top of DbgEng.dll APIs. And I acknowledge the feature quality is a disappointment, and I cannot do much about it.

The toolset and the APIs are designed around the idea that they are used on development setup, and the debugger process is another process. In contrast, the C++ feature should work everywhere, not only the development setup, and from within the same process.

The particular limitation you encountered comes from DbgEng.dll in particular. An alternative could be to implement std::stacktrace on top of DbgHelp.dll, which can look up only file name, if full path lookup failed. But DbgHelp.dll is not thread safe is more thread-unsafe than DbgEng.dll in a sense it has this unsafety warning on every function.

If you're doing post-mortem debugging, consider using dumps instead of text stack traces.

AlexGuteniev commented 2 days ago

I've reported this as one of DevCom-10692305 issues.

Ulysses1337 commented 1 day ago

I appreciate it.