Why loading symbols make Visual Studio take so long to start? - c++

I have a small Qt project written in c++ and when i debug it (Release) its taking like 7~10sec to start, even with the cache symbols saved into a local folder.
When I disable this option:
Debugging -> General -> [x] Load debug symbols in external process (Native only)
And select this option:
Debugging -> Symbols -> (*) Load only specified modules
It take around 1sec to start debugging the same project.
My computer specs:
Windows 10
Visual Studio 2022
cpu: i9 9900k
ssd: 970 evo plus (gen3 around 2~3k read/write speed)
Why such difference in time?
I'm asking because even 'disabling' the options i mentioned, intellisense is still working.
What are these symbols used for when debugging?
Does disabling these options impact in something when not debugging?

After the source code has been compiled, most of the actual names of variables will be stripped out to save space, because the actual machine code of the executable doesn't use the long string names of variables, it uses memory addresses.
So debugging symbols are used to provide information to the debugger which normally wouldn't be present in the final executable. Such as the names you provided in the source code to associate with various memory addresses. So if an error occurs, such as:
int* some_invalid_pointer = NULL;
// Segmentation fault should occur here
int some_variable = *some_invalid_pointer;
If you don't have debug symbols enabled, you may get a message such as Error: Segmentation Fault because the debugger has no idea what the name of each variable actually is. Debugging symbols give the debugger more information so it could print a message closer to Error: Segmentation Fault on Line 3: "int some variable = *some_invalid_pointer;" which is much easier to debug.
So it takes longer both because of the larger size of the executable needing to be loaded, and because debugging isn't as simple as running a version of the code compiled in debug mode. Debugging usually consists of running an actual separate Debugger executable, which then loads and runs your code. So when debugging you actually need to load and start running the Debugger, then the Debugger loads your program, which is especially slow because it could be the debugger loading it and not the OS like normal.
(To answer your final question, yes technically debugging info can be left in a release executable, but because of the way executables are usually Demand Paged into memory (You can look it up if you're interested), basically what it means is that info within an executable which is never actually referenced, shouldn't ever be loaded into memory and so it shouldn't have an impact on release runtime performance)

Related

Program crashes when outside test environment - C++

I have a program that runs fantastically when run from inside Visual Studio 2010 Express but when built and taken out, it has problems. I have set up the external test environment the same as when it is run from within Visual Studio so that shouldn't be the problem. I want to attach it to the .exe to see where the crash is but I don't have the non-Express versions.
Any suggestions? Why would a program crash outside of the the VSC++ 2010 Express environment but run perfectly inside.
I would post code but it's a huge project, not a line that would cause an error.
Thank you so much for your time.
It's very difficult to know for certain without knowing what the crash is, but a couple of common issues that may cause this:
Environment variables not the same. Perhaps you are relying on something in vcvars32.bat in your test environment.
The PATH environment variable is not the same and your picking up some bad or incompatible DLL.
Your code is somehow dependant on the current working directory being the one when run from Visual Studio.
Wikipedia to the rescue?
Time can also be a factor in heisenbugs. Executing a program under control of a debugger can change the execution timing of the program as compared to normal execution. Time-sensitive bugs such as race conditions may not reproduce when the program is slowed down by single-stepping source lines in the debugger. This is particularly true when the behavior involves interaction with an entity not under the control of a debugger, such as when debugging network packet processing between two machines and only one is under debugger control.
Also, note that User32.dll slightly changes its behavior when under a debugger, in order to make debugging easier for you. That shouldn't change anything, though.
You could debug this using the freely available Debugger Tools for Windows. There's plenty of documentation and quick start guides available, especially the chm included in the install. In your case, you may want to try the following:
Make sure you have the PDBs for your app available somewhere on a share.
Attach to the running instance of the app: windbg -p <PID>. Note that you can also start the program under the context of the debugger by doing windbg -g foo.exe.
Repro the crash.
Change the symbol path to your symbols and the Microsoft public symbol server to get proper symbols for components: .sympath x:\YourPathToPDBs; SRV*x:\symbols*http://msdl.microsoft.com/download/symbols
Tell the debugger to reload symbols using your path: .reload
Get a callstack by hitting k in the debugger.
That's the barebones you need to figure out where it's crashing. You can then go deeper and try to analyze exactly why it's crashing by looking at the debugger chm or other resources on MSDN or Tess's blog. One useful command is dv to dump local variables for a particular frame. If the callstack doesn't give line numbers, type .lines and then hit k or kb.
You could surround all code in your Main function with a try catch block. When you catch an excepcion, write to a log file the stack trace.
Then run your exe and check the log file to know where your program is crashing.
PS: Don't forget to place the *.pdb file together with the exe file, otherwise you won't be able to get the stacktrace information.
I realise this question is a couple of years old, but I have been experiencing the same thing and came upon a possible culprit (the actual culprit in my case), which may help others who have this issue.
One important difference when running an application within Visual Studio and running it outside is the Current Working Directory ("CWD").
A typical directory structure for a Visual C++ Solution/Project is along these lines:
Solution <- the location of your solution file
Debug <- where the Debug executables end up
Release <- where the Release executables end up
Project <- the location of your project file
Debug <- where Debug intermediate files end up
Release <- where Release intermediate files end up
When you execute the application from within Studio, either with "Start Debugging" or "Start Without Debugging", the default CWD is the Project directory, so in this case Solution\Project.
However, when you execute outside by simply double-clicking the application, the CWD is the application directory (Solution\Debug for example).
If you are attempting to open a file from the current directory (which is what happens when you do std::ifstream ifstr("myfile.txt")), whether it succeeds depends on where you were when you started the application.

Invalid call stack in crash dump due to mismatched/missing *system* binary file?

Got this callstack when I open a Windows crash dump in Visual Studio 2005:
> myprog.exe!app_crash::CommonUnhandledExceptionFilter(_EXCEPTION_POINTERS * pExceptionInfo=0x0ef4f318) Line 41 C++
pdm.dll!513fb8e2()
[Frames below may be incorrect and/or missing, no symbols loaded for pdm.dll]
kernel32.dll!_UnhandledExceptionFilter#4() + 0x1c7 bytes
...
Looking at the module load info:
...
'DumpFM-V235_76_1_0-20110412-153403-3612-484.dmp': Loaded '*C:\Program Files\Common Files\Microsoft Shared\VS7Debug\pdm.dll', No matching binary found.
...
We see that this binary was not even loaded, because the machine used to analyze the dump is a different machine than the machine that produced the dump.
I don't have access to this other machine at the moment -- can I somehow get this stack fixed, or will I always need the exact binary at this exact path location?
If you absolutely want to debug this dump in Visual Studio, then you can get away with copying the system DLLs from the machine that produced the dump to the same folder where your .dmp file is. That way, it will load those binaries instead of trying to find them in the same path on the debugging system as they were on the original system (which probably will contain different versions of the same modules).
As Naveen pointer out though, you won't have this problem when loading the dump in WinDBG (for reasons I have yet to understand). That is why when I get a dump from clients, I always analyze them in WinDBG.
If you need help on using WinDBG for crash dump analysis, the following Web site is full of info on the subject: http://www.dumpanalysis.org/.
Another option is to use the ModuleRescue tool from the folks at DebugInfo.com. This will scan a dump file, allow you to choose the module that isn't loading symbols, and then it generates a fake module that has just enough info in it for the debugger to load the symbols from the symbol server.
When Visual Studio can't load the symbols for this module and opens a dialog asking you to find the symbols, just point your debugger at that fake module and it will load correctly.
This tool basically does the same thing that WinDbg does, albeit with a different workflow.

Debugging c++ core files for released software

I'm trying to find a way to debug core files sent to me from released versions of my software (c++ code compiled with gcc). Ideally, I'd like to be able to deploy release builds, and keep debug builds on hand to use for debugging, so I have symbol tables, etc.
My problem is that (as I understand it) the debug and release builds are not guaranteed to be the same - so a core file from the field may just look like garbage when I fire up gdb and point to my debug executable.
Is there a way around this (and here's the catch) without impacting size or performance of my released software? It's a large application, and performance of the debug build is probably not acceptable to customers. I've looked at suggestions to build once (debug), then strip symbol tables and ship that as the release build, but I'm going to see a performance hit with that approach, won't I?
Does anyone have suggestions for things they've tried or currently use that address this problem?
Thanks!
You can compile and link with optimization turned on and still generate debug symbols (-O3 -g) and then extract the debug symbols. This way you'd have the debug symbols around but can ship without them, and you won't have a performance penalty or something. See How to generate gcc debug symbol outside the build target? on how to do that.

Loading mswsock.dll takes too much time

Everytime I run my application, loading time is too long.
So I looked output window, this was the reason. This take too much time.
'AppName.exe': Loaded 'C:\Windows\SysWOW64\mswsock.dll', Cannot find or open the PDB file
I'm using VisualStudio 2010 rightnow, but it was ok with VisualStudio 2005.
64bit, 32bit doesn't matter. I tested on both system, all slow.
Can anyone give me any idea?
Sounds like you are running your program under the Visual Studio debugger and you have the debugger set to automatically (try to) load debug symbols from Microsoft's symbol server.
When symbols for a DLL cannot be found locally or on the symbol server there is a long delay while Visual Studio works it out. Who knows why it takes so long, and why VS does not cache the fact there is no symbol available (to at least avoid checking every single time), but that's how it is.
Still, debug symbols are very useful and available for most system DLLs. Rather than turn off the symbol server completely, I find it best to make it only load symbols on demand. That way when you need them for a module you can right-click it (e.g. in a stack trace window) and tell VS to find the symbols for it.
You can do this under Tools -> Options -> Debugging -> Symbols by changing Automatically load symbols for to Only specified modules. (For modules you want the symbols to often, you can add them to the list so you don't have to keep manually pulling them in.)
Sounds like you've got a slow or malfunctioning Internet connection. Tools + Options, Debugging, Symbols, untick "Microsoft Symbol Servers".

Windows/C++: Is it possible to find the line of code where exception was thrown having "Exception Offset"

One of our users having an Exception on our product startup.
She has sent us the following error message from Windows:
Problem Event Name: APPCRASH
Application Name: program.exe
Application Version: 1.0.0.1
Application Timestamp: 4ba62004
Fault Module Name: agcutils.dll
Fault Module Version: 1.0.0.1
Fault Module Timestamp: 48dbd973
Exception Code: c0000005
Exception Offset: 000038d7
OS Version: 6.0.6002.2.2.0.768.2
Locale ID: 1033
Additional Information 1: 381d
Additional Information 2: fdf78cd6110fd6ff90e9fff3d6ab377d
Additional Information 3: b2df
Additional Information 4: a3da65b92a4f9b2faa205d199b0aa9ef
Is it possible to locate the exact place in the source code where the exception has occured having this information?
What is the common technique for C++ programmers on Windows to locate the place of an error that has occured on user computer?
Our project is compiled with Release configuration, PDB file is generated.
I hope my question is not too naive.
Yes, that's possible. Start debugging with the exact same binaries as ran by your user, make sure the DLL is loaded and you've got a matching PDB file for it. Look in Debug + Windows + Modules for the DLL base address. Add the offset. Debug + Windows + Disassembly and enter the calculated address in the Address field (prefix with 0x). That shows you the exact machine code instruction that caused the exception. Right-click + Go To Source code to see the matching source code line.
While that shows you the statement, this isn't typically good enough to diagnose the cause. The 0xc0000005 exception is an access violation, it has many possible causes. Often you don't even get any code, the program may have jumped into oblivion due to a corrupted stack. Or the real problem is located far away, some pointer manipulation that corrupted the heap. You also typically really need a stack trace that shows you how the program ended up at the statement that bombed.
What you need is a minidump. You can easily get one from your user if she runs Vista or Win7. Start TaskMgr.exe, Processes tab, select the bombed program while it is still displaying the crash dialog. Right-click it and Create Dump File.
To make this smooth, you really want to automate this procedure. You'll find hints in my answer in this thread.
If you have a minidump, open it in Visual Studio, set MODPATH to the appropriate folders with the original binaries and PDBs, and tell it to "run". You may also need to tell it to load symbols from the Microsoft symbol servers. It will display the call stack at the error location. If you try to look at the source code for a particular stack location, it may ask you where the source is; if so, select the appropriate source folder. MODPATH is set in the debug command-line properties for the "project" that has the name of the minidump file.
I know this thread is very old, but this was a top Google response, so I wanted to add my $.02.
Although a mini-dump is most helpful, as long as you have compiled your code with symbols enabled (just send the file without the .pdb, and keep the .pdb!) you can look up what line this was using the MSVC Debugger or Windows Debugger. MSN article on that:
http://blogs.msdn.com/b/danielvl/archive/2010/03/03/getting-the-line-number-for-a-faulting-application-error.aspx
Source code information isn't preserved in compiled C++ code, unlike in runtime-based metadata-aware languages (such as .NET or Java). The PDB file is a symbol index which can help a debugger map compiled code backwards to source, but it has to be done during program execution, not from a crash dump. Even with a PDB, Release-compiled code is subject to a number of optimizations that can prevent the debugger from identifying the source code.
Debugging problems which only manifest on end-user machines is usually a matter of careful state logging and a lot of detail-oriented time and effort combing over the source. Depending on your relationship with the user (for example, if you're internal corporate IT development), you may be able to make a virtual machine image of the user's machine and use it for debugging, which can help speed the process tremendously by precisely replicating the installed software and standard running processes on the user's workstation.
There are several ways to find the crash location after the fact.
Use a minidump. See the answers above.
Use the existing executable in a debugger. See the answers above.
If you have PDB files (Visual Studio, Visual Basic 6), use DbgHelpBrowser to load the PDB file and query it for the crash location.
If you have TDS files (separate TDS file, or embedded in the exe, Delphi, C++ Builder 32 bit), use TDS Browser to load the TDS/DLL/EXE file and query it for the crash location.
If you have DWARF symbols (embedded in the EXE, C++ Builder 64 bit, gcc, g++), use DWARF Browser to load the DLL/EXE and query it for the crash location.
If you have MAP files, use MAP File Browser to load the MAP file and query it for the crash location.
I wrote these tools for use in house. We've made them available for free.