strange debugging problem

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Hi there,

I have a very strange problem debugging my plugin. I am using VC2008 and try to debug by attaching to Christian Budde's Unit Test Program.

The strange thing is, that get crashes if I just run it in the Unit test (TestMultipleOpenCloseCycles), and also if I step through with the debugger.

If, however, I put an explicit breakpoint into the routine, which creates the crash on stepping through, it all works. It enters the routine, does all the stuff, exits and continues without problems. If I take out the breakpoint, it crashes again.


It is getting even more weird: sometimes, when stepping into a subroutine, I end up in a wrong routine. It seems that the addresses for routines are messed up.

Is there any way to check memory corruption?

Has anybody seen something like that before? Any ideas what I can do here? I am quite puzzled...


Thanks a lot,
Martin

Post

martin_l wrote:Hi there,

I have a very strange problem debugging my plugin. I am using VC2008 and try to debug by attaching to Christian Budde's Unit Test Program.

The strange thing is, that get crashes if I just run it in the Unit test (TestMultipleOpenCloseCycles), and also if I step through with the debugger.

If, however, I put an explicit breakpoint into the routine, which creates the crash on stepping through, it all works. It enters the routine, does all the stuff, exits and continues without problems. If I take out the breakpoint, it crashes again.


It is getting even more weird: sometimes, when stepping into a subroutine, I end up in a wrong routine. It seems that the addresses for routines are messed up.

Is there any way to check memory corruption?

Has anybody seen something like that before? Any ideas what I can do here? I am quite puzzled...


Thanks a lot,
Martin
Could it be a race condition from functions being called concurrently on different threads? And putting in the breakpoint always provides enough time for the conflicting function to win the race?

And yes, I've seen my copyprotection functions wrongly fire in FLS. Doesn't seem to happen in any other hosts. I assume somehow the instruction pointer is getting corrupted, but as I haven't been able to reproduce it myself it's been impossible to debug.

How is your plug-in behaving in production hosts, like Reaper? Some of these test hosts can be a little overzealous in their torture and worst-case scenarios.

Post

There is only really one concession I've had to make to threading issues in a VST 2.4 and that's to make a critical section around editor::close() and editor::setParameter(). This is because some hosts call setParameter while the close call is running, and if a particular control hasn't been deleted and its pointer zeroed yet, and then setParameter runs on it while its getting deleted, poof!

You probably wouldn't even need to use a critical section. You could just set up and test for a variable that would keep the two functions from running at the same time.

Post

martin_l wrote:The strange thing is, that get crashes if I just run it in the Unit test (TestMultipleOpenCloseCycles), and also if I step through with the debugger.

If, however, I put an explicit breakpoint into the routine, which creates the crash on stepping through, it all works. It enters the routine, does all the stuff, exits and continues without problems. If I take out the breakpoint, it crashes again.
Pragmatic approach: put the breakpoint behind the function. If crash, move it back into the function, just before the "return" statement (or closing brace if function returning nothing). If crash, iteratively move the breakpoint up another statement (or try do a "binary breakpoint crash search" 8-)). This won't necessarily tell you the cause, but at least the position where things go bad.
And whether the problem is reproducible.
martin_l wrote:It is getting even more weird: sometimes, when stepping into a subroutine, I end up in a wrong routine. It seems that the addresses for routines are messed up.
That is indeed strange, unless the function call happens indirectly (i.e., through a function pointer, or when calling a virtual method). If it's a virtual function in a class, some ****censored**** ruined the virtual function table.
Is there any way to check memory corruption?
Hmmm. For VS2008, check out "_heapchk()" in the VS Help. But it won't help much against, for example,
  • copying objects of different types with virtual functions over each other that don't have an appropriate copy constructor or assignment operator
  • copying objects containing pointers without duplicating the areas these pointers point to, then delete the memory areas from the first object
  • serializing complete objects out to disk and then reading them back in another program run (including, for example, the VFT pointer!)
and other "niceties" of this kind.
Has anybody seen something like that before?
That, and much worse things 8-)
Any ideas what I can do here? I am quite puzzled...
Not unless you show the code.
"Until you spread your wings, you'll have no idea how far you can walk." Image

Post

^ Very good advice.

Post

Thanks very much for the tips.

arakula wrote: Pragmatic approach: put the breakpoint behind the function. If crash, move it back into the function, just before the "return" statement (or closing brace if function returning nothing). If crash, iteratively move the breakpoint up another statement (or try do a "binary breakpoint crash search" 8-)). This won't necessarily tell you the cause, but at least the position where things go bad.
And whether the problem is reproducible.
Well, it is reproducible, depending on where I put the breakpoints. See below...
arakula wrote:
martin_l wrote:It is getting even more weird: sometimes, when stepping into a subroutine, I end up in a wrong routine. It seems that the addresses for routines are messed up.
That is indeed strange, unless the function call happens indirectly (i.e., through a function pointer, or when calling a virtual method). If it's a virtual function in a class, some ****censored**** ruined the virtual function table.
OK. I think I know a bit better what is going on here. It does not jump into some other part of the code. Rather, what happens is that the debuggers step function does not work properly. I see that at some reproducible position in the code, the next 'step' suddenly progresses the code by several function calls. I do see that it has actually performed what it is supposed to do in all those functions, only that the stepping procedure of the debugger does not stop at each line, as it should do.

If I put breakpoints into every line, I see that the code seems to work properly there. All variables look healthy and have the correct values.

When following the code in this way, it only crashes at some point inside the host, after execution of the dispatchEffectClass (or similar...) for which I don't have debugging info.

Eventually, it tries to execute a function at address 0xCCCCCCCC, which leads to an access violation.
arakula wrote:
Is there any way to check memory corruption?
Hmmm. For VS2008, check out "_heapchk()" in the VS Help. But it won't help much against, for example,
  • copying objects of different types with virtual functions over each other that don't have an appropriate copy constructor or assignment operator
  • copying objects containing pointers without duplicating the areas these pointers point to, then delete the memory areas from the first object
  • serializing complete objects out to disk and then reading them back in another program run (including, for example, the VFT pointer!)
and other "niceties" of this kind.
Has anybody seen something like that before?
That, and much worse things 8-)
Any ideas what I can do here? I am quite puzzled...
Not unless you show the code.
OK. I will continue with the heapchk() thing. Let's see whether this reveals some more...


Cheers,
Martin

Post

martin_l wrote: only that the stepping procedure of the debugger does not stop at each line, as it should do.
IIRC I have had that happen when the program database wasnt being found, (IE the debug info), this can cause the 'step' function to skip about.

martin_l wrote: Eventually, it tries to execute a function at address 0xCCCCCCCC, which leads to an access violation.
In debug mode MVSC initializes some variables to easily recognizable values like 0xCCCCCCCC or 0xDEADBEEF, stuff like that. So if you see anything like that it's best to google it and see what it means.

0xCCCCCCCC is an uninitialized pointer AFAICT. So are there any function pointers anywhere you aint initialized?
Chris Jones
www.sonigen.com

Post

martin_l wrote: OK. I think I know a bit better what is going on here. It does not jump into some other part of the code. Rather, what happens is that the debuggers step function does not work properly. I see that at some reproducible position in the code, the next 'step' suddenly progresses the code by several function calls. I do see that it has actually performed what it is supposed to do in all those functions, only that the stepping procedure of the debugger does not stop at each line, as it should do.
Source-level debugging is great and I love it, but things like that are the time to step through the disassembly directly. There may be some constructor/destructor of an inplace object doing something, which you will see then.
Cakewalk by Bandlab / FL Studio
Squire Stratocaster / Chapman ML3 Modern V2 / Fender Precision Bass

Formerly known as arke, VladimirDimitrievich, bslf, and ctmg. Yep, those bans were deserved.

Post

sonigen wrote:
martin_l wrote: Eventually, it tries to execute a function at address 0xCCCCCCCC, which leads to an access violation.
In debug mode MVSC initializes some variables to easily recognizable values like 0xCCCCCCCC or 0xDEADBEEF, stuff like that. So if you see anything like that it's best to google it and see what it means.

0xCCCCCCCC is an uninitialized pointer AFAICT. So are there any function pointers anywhere you aint initialized?

Code: Select all

0xABABABAB : Used by Microsoft's HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory
0xABADCAFE : A startup to this value to initialize all free memory to catch errant pointers
0xBAADF00D : Used by Microsoft's LocalAlloc(LMEM_FIXED) to mark uninitialised allocated heap memory
0xBADCAB1E : Error Code returned to the Microsoft eVC debugger when connection is severed to the debugger
0xBEEFCACE : Used by Microsoft .NET as a magic number in resource files
0xCCCCCCCC : Used by Microsoft's C++ debugging runtime library to mark uninitialised stack memory
0xCDCDCDCD : Used by Microsoft's C++ debugging runtime library to mark uninitialised heap memory
0xDEADDEAD : A Microsoft Windows STOP Error code used when the user manually initiates the crash.
0xFDFDFDFD : Used by Microsoft's C++ debugging heap to mark "no man's land" guard bytes before and after allocated heap memory
0xFEEEFEEE : Used by Microsoft's HeapFree() to mark freed heap memory
So, uninitialized stack memory.
Cakewalk by Bandlab / FL Studio
Squire Stratocaster / Chapman ML3 Modern V2 / Fender Precision Bass

Formerly known as arke, VladimirDimitrievich, bslf, and ctmg. Yep, those bans were deserved.

Post

Chris Walton wrote:

Code: Select all

0xABABABAB : Used by Microsoft's HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory
0xABADCAFE : A startup to this value to initialize all free memory to catch errant pointers
0xBAADF00D : Used by Microsoft's LocalAlloc(LMEM_FIXED) to mark uninitialised allocated heap memory
0xBADCAB1E : Error Code returned to the Microsoft eVC debugger when connection is severed to the debugger
0xBEEFCACE : Used by Microsoft .NET as a magic number in resource files
0xCCCCCCCC : Used by Microsoft's C++ debugging runtime library to mark uninitialised stack memory
0xCDCDCDCD : Used by Microsoft's C++ debugging runtime library to mark uninitialised heap memory
0xDEADDEAD : A Microsoft Windows STOP Error code used when the user manually initiates the crash.
0xFDFDFDFD : Used by Microsoft's C++ debugging heap to mark "no man's land" guard bytes before and after allocated heap memory
0xFEEEFEEE : Used by Microsoft's HeapFree() to mark freed heap memory
So, uninitialized stack memory.

Thanks a lot. Unfortunately, I got my message wrong, when I replied, as I was not at my development computer. I checked it again, and got a access violation at DDDDDDDD.

Where did you find this information?

By the way, I started using the _heapchk() and found that at some point the heap gets corrupted. Somehow, the host (vsthost) tries to access memory outside the heap. I will now start digging down to try to find where that happens.


Cheers,
Martin

Post

Just some quick google search.

Then again, having done C++ with VS professionally for a while, I know the important half of those by heart now :hihi:
Cakewalk by Bandlab / FL Studio
Squire Stratocaster / Chapman ML3 Modern V2 / Fender Precision Bass

Formerly known as arke, VladimirDimitrievich, bslf, and ctmg. Yep, those bans were deserved.

Post

OK. I found one source of heap corruption and seem to have solved that one.
The plugin is behaving well in vsthost now.

However, I still got the DDDDDDD crash in plugin unit test. This appears to indicate that I am addressing memory which was freed after a delete call.

Here is another question to experts: I am using STL lists for some book-keeping.
On www.cplusplus.com it says
Removes from the list all the elements with a specific value. This calls the destructor of these objects and reduces the list size by the amount of elements removed.
but it seems that remove does not delete the object, hence i have an additional delete 'object' after list.remove('object').

My 'objects' are actually pointers to real objects such as buffers, etc.

Code: Select all


class Buffer
{
int length;
float *data  // allocated in Buffer()
}
;
list<Buffer*> bufferList;

Buffer *myBuffer;

... 

myBuffer = new Buffer;
bufferList.push(myBuffer);

...

bufferList.remove(myBuffer);
delete myBuffer;

Could that last delete cause the trouble??
If I look at myBuffer in the debugger, the pointers myBuffer and data are still valid after the list.remove() call, and only are wiped out after the delete call, so it looks alright.


Cheers,
Martin

Post

martin_l wrote:but it seems that remove does not delete the object,
Remove deletes the list elements, but in your case the elements are just pointers, so the pointers themselves are deleted, but not the objects that the pointers are pointing to. Using the delete after remove is correct (unless someone else is still using the object at that point).

Post

DigitalCEM wrote:..unless someone else is still using the object at that point).
You know you're in the company of geeks when they refer to code as people :wink:

Geeks Rule!

Post

Ichad.c wrote:
DigitalCEM wrote:..unless someone else is still using the object at that point).
You know you're in the company of geeks when they refer to code as people :wink:

Geeks Rule!
Yep. My code comments often refer to "we". // next we check if...

I'm in there!!!

Though really by "we" I mean, me, the original author, and you (who is probably also me, just in the future) the poor bastard trying to figure out what the original author intended when he wrote it.

Post Reply

Return to “DSP and Plugin Development”