Search code examples
c++debuggingvisual-studio-2019pdb-files

Unable to debug C++ executable ("The breakpoint will not currently be hit")


I have a test executable linking a C++ static library in Visual Studio 2019 (16.4.2) on Windows 10. When I launch the debugger, all breakpoints in test cilent and library code appear hollowed-out with a tooltip that the PDB could not be located:

"The breakpoint will not currently be hit. No symbols have been loaded for this document."

After launching the debugger, manually browsing for the executable PDB from the link on the "No Symbols Loaded" screen also fails with the message:

"A matching symbol file could not be found in this folder"

This odd as the file is there, it is up-to-date, and the PDB browser lets me select it. It is the correct PDB (specified in Linker > Debugging settings), not the much smaller intermediate-folder one.

I am building Debug|x86 and get the same issue in Debug|x64. My test executable is using Google Test version 1.8.1.2.

I have tried deleting all intermediate files and output, closed/reopened the IDE and rebuilt the solution, but this hasn't helped. The PDB is not being overwritten by an identically-named one from some other project.

The project settings I have are as follows:

Test executable AND static library:

C/C++ > General: Debug Information Format = Program Database (/Zi).

Test executable:

Linker > Debugging: Generate Debug Info = Generate Debug Information (/DEBUG)

Linker > Debugging: Generate Program Database File = $(OutDir)$(TargetName).pdb

The 3rd party Google test PDBs are present in the output folder, copied by the build from the NuGet package I am using. I have checked these are the correct PDBs. I don't think I need these anyway as I'm not trying to debug into any Google test code.

I have tried creating a new "Hello world" test executable and can debug into that without any problem.


Solution

  • After much trial and error I hit on the answer.

    A project with executable target (EXE or DLL) generates TWO PDBs:

    1. Intermediate PDB: only for the project's code, written to the intermediate folder

    Specified in Configuration Properties > C/C++: Program Database Filename

    1. Output PDB: for the whole executable including statically linked libraries, written to the output folder

    Specified in Configuration Properties > Linker > Debugging: Generate Program Database File

    The problem was caused by overriding the name of the executable's intermediate PDB, changing it from its default value to the project (a.k.a. target) name. The output PDB (much larger and written to the output folder) shared the same file name.

    The intermediate PDB name override was inherited from common property pages shared with the static library project. The latter needs this override because it is distributed with its PDB. Retaining the default name (vc142.pdb) might conflict with other default-name PDBs further down the line.

    The fix was to restore the default name of the intermediate PDB in the executable project:

    1. Open project properties.
    2. Expand Configuration Properties > C/C++
    3. Revert the value of Program Database Filename: choose < inherit from project or parent default > from the value dropdown. Click Apply.

    This sets the value back to something like $(IntDir)vc$(PlatformToolsetVersion).pdb.

    Cliffs: Any DLL/EXE project should avoid specifying the same PDB filename for its intermediate and final (output) PDB.

    The linker could have been more helpful in this regard, perhaps by issuing a link-time warning in the event of a user-generated conflict such as this.