Click here to Skip to main content
15,072,746 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
We're developing plugins for a third party executable with a C++ API. There is no SDK available for the executable, and, worse, no debug version. The API uses at the very least std::vector and MFC CString which to my knowledge are not compatible between debug and release builds. Therefore we can only use release builds for our DLL.

Given this setup, it's extremely difficult to debug our code. While we can attach the debugger at runtime, much of our code is optimized away, we cannot inspect any variables, the step over command tends to step into foreign code, and half of our code is never reached.

Pretty much the only thing we can achieve with debugging is catching an exception to see the call stack where it happens, and even that doesn't work reliably.

I'm at a loss how to improve matters, as it doesn't seem said third party is willing to deliver a debug version for us.

Does anyone have a suggestion what we could try to improve our debug capabilities?

The only idea left is creating a wrapper over the entire API that converts all types that are not compatible between builds into ones that are. But the API is huge, our team is minute, and we get new versions every year ...

What I have tried:

We told the compiler to build a PDB and to not optimize code at all in the release version, but it doesn't seem to have any effect: symbols and code are still optimized away. I have no idea why we cannot at least see variable contents within our code, and how to fix that.

I've also searched for advice across the web, repeatedly, but in the end the answer always was: get a debug build. And that is not going to happen.
Posted
Updated 3-Aug-21 18:24pm

In this cases I like to write a log file with the debug texts and some error messages. Best is to check the amount of written data in some debug tests and only log errors and problems.
Normally the problematic code areas are knows so concentrate the output there. Dont ferget some processed data and time stamping for reproducing the issues.
   
Comments
Stefan_Lang 2-Aug-21 7:52am
   
Thanks, we're already using logging, but it's tedious and impractical, because the API functions take either a lot of arguments as input, or objects consisting of a lot of data, or both. Not to mention the API objects are _huge_, and it's incredibly hard to pinpoint which of the data members are actually important. And many can't be accessed directly, so the only chance to actually see the contents would be the debugger.
KarstenK 2-Aug-21 10:15am
   
You need to concentrate on the real issues. Maybe you write more verification code to exclude error causes.
Or you contact the vendor of your libraries to get debug version. They should also be interested in finding the bugs in THEIR OWN code. So you havent as bad cards as you might think. Best is to drill down to their development team.

BTW: sometimes it helps to turn off release optimization. It sometimes is changing the errors to the real cause :-O
Stefan_Lang 2-Aug-21 11:08am
   
You're right, of course, but unfortunately it doesn't seem the people I talk to on the vendors side are even half as reasonable. It doesn't help their codebase is > 30 years old, and the developers as well as the clients have learned to live with the system as is...

That said, confronting them with the argument that getting a debug version could help me finding bugs in their code might be a good idea.
KarstenK 3-Aug-21 7:36am
   
Sounds like you need to implement some workarounds or end using that component. I recommand to explore the options and costs to use other software. It maybe some man month but would end pain in the ass and lower downtime. It is always a great talking point and also updating your personal skills.
Stefan_Lang 3-Aug-21 8:24am
   
I'ts not a component, it is the main app, and our company develops plugins specifically for it. Switching to another is not an option.
KarstenK 3-Aug-21 10:58am
   
Sounds like legacy M$ product from the pre internet era. :-O
Release builds have reached the point where the trade-off between performance and debugging is unacceptable. I'm using VS2017 and face the same problems. Here[^] are the compiler settings I use. They help, but it's still not as easy as a debug build.

You might also get some ideas from my article on debugging live systems[^], though most of what it discusses requires some infrastructure that you may not have the time to build or import.
   
Comments
Stefan_Lang 2-Aug-21 7:48am
   
Thank you. I will try these. One question: just how much of a problem is that CLR setting (C/C++ > General > Common Language RunTime Support: No CLR Support)? I'm asking because we need to use CLR. I've already looked into splitting our DLLs into one encapsualting the CLR part and one pure native DLL. The former would be highly reusable, so it makes sense to do anyway.
Greg Utas 2-Aug-21 8:22am
   
I don't think using CLR should make the code less debuggable. Note that this link (https://docs.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?view=msvc-160) says that /EHa (to also catch Windows structured exceptions) is mandatory when using CLR. Scroll down to "Exception handling under /clr".
Stefan_Lang 9-Aug-21 10:44am
   
I tried the settings according to the link you provided, but unfortunately the use of CLR does conflict with the debuggers' ability to display variable contents. Apparently it can't cope with a binary that sometimes does and sometimes doesn't use managed objects, at least in Release mode :-(

I am now considering to separate the CLR part from the rest, into a separate library, but it will take some tim eto implement...
When I have done this I disabled optimizations in the release build of the library and enabled writing of the debug symbols file. I then set the hosting executable program for debugging the library to be the one in question and then set break points in the functions of my library. This worked out great too. I could see all the data passed into the library and step through it and so on.

I once spent a day and a half debugging a problem I was having and it turned out that Microsoft's RTL had an additional data member in the FILE structure in debug mode so code that took a FILE pointer as an argument always had to be in the same build mode as the hosting executable. In the end I decided that code to read files couldn't pass a FILE pointer into the library - it all had to live in the library and that solved the problem.
   
Comments
Stefan_Lang 3-Aug-21 8:32am
   
As I already stated I've considered wrapping the API so that all objects passed into and out of it would first be translated into ones that are the same in debug and release builds. The wrapper would be separated into a release build DLL, but the rest of the DLL could then be Debug.

I think this should work, but it would be too much effort, both to develop and to maintain.
You can include debug information in the release build. It will behave as if it was debug build, i.e. stepping through code, breakpoints in code etc.
   
Comments
Stefan_Lang 6-Aug-21 5:02am
   
See the "What have I tried" section. Didn't work.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900