Why?

Well debugging exe is quite easy, but ever wondered how to debug a dll. Well why? Simple, you write a dll and you wanna debug a bug just like you would do with an executable.

Can you give us some examples?

Well so what is a dll? I think of it as a parasite because just like a parasite it’s dependent on an executable to get it running. Some examples follow…

  1. A good example to think of will be rundll32.exe. Ever thought about that name “rundll32.exe”, it just means “run a 32 bit dll using this exe”, so how does this achieve this, remember the command line that we pass to it, i.e. name of the dll followed by a procedure name exported from our dll.
  2. Another example to think of is regsvr32.exe, does the same stuff i.e. registers a COM dll but this time with a difference, we don’t have to give a procedure name. Because COM programming protocol defines mandatory functions to be exported from a COM dll and regsvr32.exe knows exactly which function to call based on the command line switches passed in.
  3. Another example that comes to mind is the windows surrogate process “dllhost.exe”, I’ve heard people say that it’s a virus ;) . Naah it’s a COM surrogate process which helps in hosting a COM dll to make the dll behave like a process hence providing the flexibility to behave like an executabable and at the same time like a dll, vice versa is not possible. Well it can at times be hosting a malicious dll too. It’s quite rare though.

What has this got to do with debugging a DLL?

The reason why I’ve given above examples is to help you understand that a DLL cannot run by itself, it needs a host process to help it run.

Exactly! same for debugging it needs a process to get it running so that execution reaches our breakpoint that we’ve set. Aha! so there must be some option to tell the debugger about the host process. Oh yeah, goto Project settings->Debugging->Executable for Debug Session. Select any process which is using your dll.

Think that you are writing a window’s shell extension, which are dlls, think on how to debug them. So for this case your target process will be explorer.exe. So you will specify explorer.exe as your process. Or imagine writing an activex control, so for this case the target process will be an activex test container.

This is a shot from VC6, it’s quite similar in VC7, VC8 and VC9, instead of tabs there you have a tree menu holding the “Debugging” item right at the top of the tree.

Well now just press F5 and see what happens, you will see your target process running and just try doing a button or menu click that could invoke the function in which you’ve set a breakpoint.  If you are writing a shell extension for e.g. extending shell context menu, then you would right click on a file in the explorer window.

Also note that if your active project is a ‘dll project’ then you’ll get prompted to enter a target process name to get the dll hosted as soon as you press F5. So no need to go to project properties.

Hope this helps you?

Share
 

I will explain very briefly, how to fix crashes in release builds of VC applications.

Difference between debug and release builds

Well so what’s the difference between release and debug builds? The only major difference is that debug builds are for debugging purpose and release builds are for end users so for this purpose debug builds contain additional debug information, this is why there is considerable size differences in binaries for debug and release.

Common reasons for crashes in release builds

Well not too many steady reasons for crashes in release builds, but some to think of I will list here…

  1. Uninitialized variables
  2. Uninitialized pointers
  3. Always set a pointer to NULL after deletion
  4. Invalid iterators (std::iterator)
  5. Crap code
  6. Array index out of bounds for array and other stl classes.
  7. Too much optimization.
  8. RTTI project settings.

Check out above reasons if there is a crash in your release builds.

So tell us how to fix issues in release builds

  • Learn assembly. :P Joking! Naah not everyone has time to learn assembly but hey it’s good to have basic knowledge on this topic.
  • Enable debug information for your release binaries. Ha, but will this increase the size of my release binaries. Nope! An extra file called a pdb (Program database) is created, which helps the JIT or any debugger to list out symbols used in your applications.
  • Always keep an updated set of symbols for all binaries; debuggers do download them automatically if you set _NT_SYMBOL_PATH to point to a symbol server. More information on how to set a symbol path is here.
  • Stop writing crap code.

Make my release build a debug build

If you are in the process of development and then you notice a crash while testing release build and you don’t know where the crash is taking place, do the following…

  1. Enable debugging for your release builds
  2. Go to C-C++/Optimizations/ and select Disable(Debug). If you don’t enable this bit you will see weird behavior while debugging. For e.g. addresses show as NULL even for valid objects on stack. By the way this might even be the cause of those crashes so initially you can leave it as it is but watch out for weird behaviors, don’t be surprised.
  3. Go to C-C++/Debug Info/ and select Program Database, this will generate a pdb file.
  4. If the output for a particular project is of .lib type then this much will suffice.
  5. Now for dlls and exes, follow steps 1 – 3.
  6. Go to Link tab/section and enable “Generate debug info”, this will add further debugging information to your exe or dll. Will show real deep stack traces with values of passed in parameters.

Yup now your release exe/dll/lib is now in full fledged debugging form. An additional thing to note is that _DEBUG is not enabled so AfxTrace, TRACE, TRACE0, TRACE1, TRACE2, ASSERTs, and VERIFYs won’t work.

Hope this helps you guys! :)

Share
 

Ever felt the need to watch over return values from functions! Well I did always but unfortunately couldn’t come up with something! I was reading through one of John Robbins’ Bugslayer articles in MSDN and found an interesting tip related to seeing function parameters passed in by adding a watch statement over the ESP stack pointer variable.

So that got me thinking like “why not EAX”, huh that was easy! So this tip happens due to the tip given by one of the readers of John’s article in Bugslayer. I will put a link to that tip once I find it along with the author’s name.

Now let me tell you how the watch statement for our tip should look like…

  1. To watch string values returned by functions…
    (char*)EAX
  2. To watch integer values returned by functions…
    (int*)EAX
  3. To watch objects returned by functions…
    (CMyObject*)EAX

Now you may ask why do I need this, I can always use the auto variable debug window. Well don’t forget that we are adding watch to a register (EAX), so this means even raw function call’s return value is shown here.

Let me show you a live case where you may need this. See here I’ve got four function calls which does some strange operations but return values doensn’t matter hence they are not stored. It’s just useless to store return values in temporary var just for the purpose of debugging, so above watches come handy.

DoOperationReturnBool(); // Returns bool, but returned values not stored
DoOperationReturnEnum(); // Cast EAX to appropriate enum type or int
DoOperationReturnCharPtr(); // Cast EAX to char pointer  or wide char ptr
DoOperationReturnObject(); // Cast EAX to appropriate object type, I haven’t tested this but should work

I am using this these days, yet to see a drawback, tell me if you find any! Have fun debugging :)

Share
 

So you have a dialog while you are debugging an application and you don’t know from where this dialog is popping up, huh, how many time has this happened!

So what normally people do is goto debug menu, press break and then goto threads and then double click on each thread to view call stack and then they find out. This is fine if you have a modal dialog, but what if it’s modeless?

So here is the solution, to break into an application while it’s running press “F12″. Yeah “F12″, can’t believe your eyes, do and believe!

So in order to debug into modeless dialogs you need to be real fast in pressing F12 ;) . As soon as you start such a dialog press F12. This does the trick for me and must do for you too!

This same trick applies to any code that you are executing, at any time to break while debugging press “F12″. This doesn’t require visual studio to be running in the foreground. The foreground application should be the application that’s being debugged. After breaking into the process, continue as you would normally to find out where exactly and in which thread the execution is taking place.

Share
© 2012 bits and bytes Suffusion theme by Sayontan Sinha