VS2017 blocking on non-existing object files when debugging with pdb file
Asked Answered
C

2

6

We are in the process of switching Visual C++ projects to the vc141 toolchain (VS 2017). We have encountered a problem where Visual Studio is unable to use a .pdb file whose source .obj files don't exist anymore (for example because they have been compiled on a build server).

Let's take a very simple executable project:

#include <iostream>

int main() {
    std::cout << "Hello world\n";
    std::cin.ignore();
}

The .vcxproj file is all default, except for <GenerateDebugInformation>true</GenerateDebugInformation> to generate the pdb file.

Reproduction steps are, always using VS2017:

  • Compiling the project
  • Placing a breakpoint inside main
  • Removing the intermediate Debug/ directory containing the .obj files
  • Disabling build-on-run through the configuration manager (so it won't recreate them)
  • Starting a debug session

This works fine with the vc100 (VS 2010) toolchain, and the breakpoint works, but it immediately triggers the following error with vc141:

Error: Unable to open file
<path>\Debug\main.obj. Error code = 0x80070003.

This very generic error code corresponds indeed to FACILITY_WIN32/ERROR_PATH_NOT_FOUND. The path to main.obj can be found inside both versions of the .pdb file, thus it is unclear to us why VS suddenly breaks down when it doesn't find it.

The "Modules" view shows that the .pdb file seems to be loaded correctly. Additionally, the breakpoint's tooltip shows the following error:

The breakpoint will not currently be hit. Unexpected symbol reader error while processing MyUser_141.exe.

What could be a solution or a workaround for this problem, given that we cannot debug on the machine that compiles the binaries in our real-case application?

Here is the full .vcxproj file:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <VCProjectVersion>15.0</VCProjectVersion>
    <RootNamespace>MyUser_141</RootNamespace>
    <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
    <ProjectGuid>{90982029-29B8-4C9B-AFB7-B8F555F15C1E}</ProjectGuid>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v141</PlatformToolset>
    <CharacterSet>MultiByte</CharacterSet>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="Shared">
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Link>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="main.cpp" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Further research:

  • We tried some other toolchain versions. The bug is not present in v14.0 (VS 2015), but is present as soon as 14.11 (VS2017 15.3).

  • Using v141_xp, which as far as we can tell uses the same toolchain but older system libraries, works.

Chinn answered 23/5, 2018 at 13:11 Comment(14)
Well apparently the new toolchain needs the object files, too.Necessary
@Necessary this would be far from practical, but in any case we just tried moving the .obj file next to the executable, and the error message doesn't change. VS definitely tries the one path, and bails out if it fails.Chinn
@Necessary That's not my experience. I routinely delete my .obj files when I seal off a release and I can still debug the .exe, no problem. Quentin, what do you mean by 'toolchain'? Are you referring to the platform toolset? If so, I'm using v141_xp, so if that works for your app you might try it.Scoot
@PaulSanders I am (<PlatformToolset>v141</PlatformToolset>). I just tried v141_xp: VS hallucinates an error about the source file being out-of-date, but once overriden everything works. Unfortunately I don't think switching to another toolchain altogether is possible, but this is certainly interesting.Chinn
Certainly is. I'm glad I found out about this. I don't know if this is what you mean, but VS would / should rebuild your entire project when you switch platform toolset. You're still using the same tool chain by the way. That's the compiler, linker and whatever. The platform tool set is the set of libraries you link against (which makes the behaviour you are seeing even more bizarre).Scoot
@PaulSanders Switching between v100 and v141 definitely switches compilers, however it makes sense that switching to v141_xp only switches system libraries. The problem I have is that all of our projects here are using v141 and can't be retargeted that easily (for organisational as well as technical reasons).Chinn
My crystal ball says that the executable was linked with the /DEBUG:FASTLINK option. Which links fast by leaving debug info in the intermediary files instead of trying to construct a clean PDB file. Not an option you'd ever need on a build server.Mahaffey
@Quentin: Ah yes, silly me, the ABI has changed since VS2010.Scoot
@HansPassant: close, so close, but not quite. The change you need to make is Configuration Properties -> Linker -> Debugging -> Generate Debug Info Generate Debug Information optimized for sharing and publishing. That seems to do the trick. The v141_xp thing was a red herring (and, fwiw, does use the same compiler). Weirdly, my projects are using the FASTLINK option yet I don't have this problem.Scoot
@Quentin: Did you see the fix? Looks good to me.Scoot
@PaulSanders this looks very promising, unfortunately(?) my workday ended and I'm running linux over here... Be assured that I'll try that first thing tomorrow morning!Chinn
@PaulSanders that was it! This is unbelievable... Would you mind making this an answer?Chinn
Sure thing. I know Hans posted a big clue but I did get there independently, God's honour.Scoot
@PaulSanders well just duel to the death to decide or something. I'm off to raise goats and forget about that insane toolchain.Chinn
S
7

To fix this, make the following change in the property pages of the project(s) that build your executable(s) and DLL(s):

Configuration Properties -> Linker -> Debugging -> Generate Debug Info -> Generate Debug Information optimized for sharing and publishing

Visual Studio Property Page

Static libraries, having no link step, don't need this. .EXEs and DLLs do.

Scoot answered 24/5, 2018 at 8:36 Comment(0)
M
1

When you specify /DEBUG with no additional options, the linker defaults to /DEBUG:FULL for command line and makefile builds, for release builds in the Visual Studio IDE, and for both debug and release builds in Visual Studio 2015 and earlier versions. Beginning in Visual Studio 2017, the build system in the IDE defaults to /DEBUG:FASTLINK when you specify the /DEBUG option for debug builds. Other defaults are unchanged to maintain backward compatibility. Source : https://developercommunity.visualstudio.com/content/problem/259283/error-unable-to-open-file-mainobj-error-code-0x800.html

Mortification answered 7/8, 2019 at 14:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.