www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Memory corruption rant.

reply Jesse Phillips <jessekphillips+D gmail.com> writes:
I would love to post a bug with a minimum test case, so that I'd be able to
identify if its my fault, the compiler, or libraries I'm using. But at this
time I can't seem to reduce it to a reasonable (non-proprietary) portion of
code. So for now I'll just rant.

I combining much here. I have two DLL's being loaded. One is Lua, being
accessed with LuaD, and the other is a DLL my company has produced. I've been
able to get some nice interaction between the three. The company DLL will make
function calls which are passed through D into Lua and the result back through
D and all this great stuff.

But I've been fighting with delegates and objects disappearing (I think LuaD
might not be preserving anonymous delegates, which I can't reproduce in the
small). I have some code that has this general flow:

auto myObj = new Object();

// Create lua and company dll objects
// call some functions for lua
// call some functions for company dll
// Other heavy processing with D only (takse > 60 seconds)
//  make a call to company dll (takes > 30 seconds)

writeln("I"m still ok")
writeln(myObject is null); // Crash with access violation

I can remove the last call to the company dll and everything is fine. And this
has been working for some time until recently when I changed some stuff on the
heavy D processing side (added a struct into the mix).

I'm not even accessing myObject, I'm just asking if it has a value it shouldn't!

In all other respects it has been a blast combining all this.
May 17 2011
next sibling parent reply Trass3r <un known.com> writes:
Could it be a stack corruption?
May 17 2011
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Trass3r Wrote:

 Could it be a stack corruption?
That would make the most sense for the behavior I'm seeing, but I don't really know how to corrupt the stack without using ASM, and even then I'd probably fail.
May 17 2011
parent Trass3r <un known.com> writes:
Am 18.05.2011, 03:51 Uhr, schrieb Jesse Phillips  
<jessekphillips+D gmail.com>:
 Trass3r Wrote:

 Could it be a stack corruption?
That would make the most sense for the behavior I'm seeing, but I don't really know how to corrupt the stack without using ASM, and even then I'd probably fail.
Could also be a backend bug. You should debug it at asm level.
May 18 2011
prev sibling next sibling parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Wed, 18 May 2011 02:18:22 +0300, Jesse Phillips  
<jessekphillips+D gmail.com> wrote:

 [snip memory corruption rant]
I've nothing to contribute but by own anecdotal experience. So: are you doing *any* allocations or throwing exceptions in finalizers (destructors of objects on the heap)? If you are, don't do it. :P -- Best regards, Vladimir mailto:vladimir thecybershadow.net
May 17 2011
parent Jesse Phillips <jessekphillips+D gmail.com> writes:
Vladimir Panteleev Wrote:

 On Wed, 18 May 2011 02:18:22 +0300, Jesse Phillips  
 <jessekphillips+D gmail.com> wrote:
 
 [snip memory corruption rant]
I've nothing to contribute but by own anecdotal experience. So: are you doing *any* allocations or throwing exceptions in finalizers (destructors of objects on the heap)? If you are, don't do it. :P -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Well I do use allocations to get values out of dll calls, but I didn't want to negotiate ownership so I duplicated everything it gave me and promptly freeing it through the free function it provides, and I ignore ownership of the values I give it (so I wouldn't be surprised if I had memory leaks, but it's not like the DLL will tell me when it is done with the memory) As for the destructor thing, I'll have to check, I originally tried to use a reference counted struct and believe I may had thown something in a destructor there (think that one is safe?). But when I move to class I'm pretty sure I just gave up on cleaning up. I mean I'm done with it when I exit my program anyway. And thing thing is that it is consistent. In that a build that fails will always fail and a build the succeeded always continues to function. So not only should it not be destroying anything yet, it really seems to be how the code is generated. I actually had a print statement which printed some values of StopWatch, and I could consistently use that to get an access violation, and I just hoped I wouldn't have any more issues. What does D do when it runs out of stack space? (Not that it is likely I am)
May 17 2011
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
Jesse Phillips Wrote:

 writeln("I"m still ok")
 writeln(myObject is null); // Crash with access violation
try writeln("I'm still ok"); writeln(0); writeln(false);
 I'm not even accessing myObject, I'm just asking if it has a value it
shouldn't!
Did you try a debugger? At least, you can see where it crashes.
May 18 2011
parent Jesse Phillips <jessekphillips+D gmail.com> writes:
Kagamin Wrote:

 Jesse Phillips Wrote:
 
 writeln("I"m still ok")
 writeln(myObject is null); // Crash with access violation
try writeln("I'm still ok"); writeln(0); writeln(false);
All those print.
 I'm not even accessing myObject, I'm just asking if it has a value it
shouldn't!
Did you try a debugger? At least, you can see where it crashes.
I'm pretty sure it crashes any time a Look at an object. I placed a print statement after where I said it crashes and it doesn't print. So while it isn't definitive, I'm pretty confident. On top of that with -g Optlink will fail with: Unexpected OPTLINK Termination at EIP=0042781B EAX=00000000 EBX=00000204 ECX=000000E2 EDX=04020B9E ESI=0043E664 EDI=01324000 EBP=0012FFF0 ESP=0012FF70 FIrst=00402000 Again, without a good test case this is probably useless, and I'll look into updating dmd/optlink when I update my libraries for the new compiler (DUI, LuaD).
May 18 2011
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
Kagamin Wrote:

 Jesse Phillips Wrote:
 
 writeln("I"m still ok")
 writeln(myObject is null); // Crash with access violation
try writeln("I'm still ok"); writeln(0); writeln(false);
or writeln("I'm still ok"); writeln("2"); if(myObject is null) writeln("3"); else writeln("4"); writeln(0); writeln(false);
May 18 2011
parent Jesse Phillips <jessekphillips+D gmail.com> writes:
Kagamin Wrote:

 Kagamin Wrote:
 
 Jesse Phillips Wrote:
 
 writeln("I"m still ok")
 writeln(myObject is null); // Crash with access violation
try writeln("I'm still ok"); writeln(0); writeln(false);
or writeln("I'm still ok"); writeln("2"); if(myObject is null) writeln("3"); else writeln("4"); writeln(0); writeln(false);
Prints everything up to 2.
May 18 2011
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
Jesse Phillips Wrote:

 writeln("I'm still ok");
 writeln("2");
 if(myObject is null)
   writeln("3");
 else
   writeln("4");
 writeln(0);
 writeln(false);
 Prints everything up to 2.
You should look at it in debugger at assembly level. There's no need to compile it with debug symbols, they'll be of no use for you. I suspect EBP==0.
Jun 02 2011
parent Kagamin <spam here.lot> writes:
Kagamin Wrote:

 Jesse Phillips Wrote:
 
 writeln("I'm still ok");
 writeln("2");
 if(myObject is null)
   writeln("3");
 else
   writeln("4");
 writeln(0);
 writeln(false);
 Prints everything up to 2.
You should look at it in debugger at assembly level. There's no need to compile it with debug symbols, they'll be of no use for you. I suspect EBP==0.
writeln("I'm still ok"); asm { cmp EBP,0; ja ok; hlt; ok: nop; } writeln("Still ok"); if(myObject is null) writeln("3"); else writeln("4");
Jun 02 2011
prev sibling parent Kagamin <spam here.lot> writes:
Kagamin Wrote:

 writeln("I'm still ok");
 asm
 {
  cmp EBP,0;
  ja ok;
  hlt;
 ok: nop;
 }
 writeln("Still ok");
 if(myObject is null)
    writeln("3");
 else
    writeln("4");
without hlt: asm { cmp EBP,0; ja ok; call _msg; ok: nop; } extern(C) void msg() { writeln("msg hit"); assert(0); }
Jun 02 2011