www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Extra argument being passed?

reply Malcolm Sharpe <masharpe2000 yahoo.ca> writes:
I am trying to port a small C++ program using DirectShow to D.  Mostly, 
it has been working fine.  However, one method call has problems with a 
null reference being passed, even though there is no argument.  I'll 
snip out the relevent sections of code (minus some error-checking) to 
clarify:

// dshow.d

module dshow;

...

interface IMediaEvent : IDispatch
{
extern (Windows):

...

	HRESULT WaitForCompletion(long msTimeout, long * pEvCode);

...

}

...


// test.d

import dshow;

...

IMediaEvent event = null;

...

graph.QueryInterface(&IID_IMediaEvent, cast(void**)(&event));

...

long evCode;
event.WaitForCompletion(INFINITE, &evCode);

...


The program has an access violation on that last line 
(event.WaitForCompletion).  It turns out it is a null reference problem. 
  According to the Visual Studio debugger, this is the disassembly for 
that last line:


00402169  lea         eax,[evCode]
0040216C  push        eax
0040216D  push        0
0040216F  push        0FFFFFFFFh
00402171  push        dword ptr [event]
00402174  mov         ecx,dword ptr [event]
00402177  mov         edx,dword ptr [ecx]
00402179  call        dword ptr [edx+24h]
0040217C  add         esp,20h
0040217F  mov         dword ptr [ebp-4],0
00402186  jmp         +18Ch (40219Ch)


The interesting line is 0040216D.  It seems something is being pushed 
onto the stack in between INFINITE and &evCode.  I'm still somewhat of a 
new programmer, so I don't know exactly what's going on here, but I can 
hazard a guess that the 0 is an argument that is being mistakenly passed 
to WaitForCompletiion.  If I step to the offending line and then set the 
execution to the next line (thereby running every line except the 
offending line) the code works and evCode is assigned a value.

Clearly something's up.  Any ideas?  I can post the full code of the 
program if I need to, but there are about 1000 lines between both files.

- Malcolm Sharpe
Jun 01 2004
next sibling parent Malcolm Sharpe <masharpe2000 yahoo.ca> writes:
I should probably mention the command line I am compiling with:

dmd.exe test.d dshow.d uuid.lib ole32.lib -g -gt -debug
Jun 01 2004
prev sibling next sibling parent reply Stephan Wienczny <wienczny web.de> writes:
See Comments

Malcolm Sharpe wrote:
  >
 00402169  lea         eax,[evCode]		//Calculates relative address of evCode
 0040216C  push        eax			//pushes that value onto the stack
 0040216D  push        0			//pushes 0 on the stack
 0040216F  push        0FFFFFFFFh		//pushes infinite on the stack
 00402171  push        dword ptr [event]	//pushes event as dword onto stack
 00402174  mov         ecx,dword ptr [event]	//moves event into ecx
 00402177  mov         edx,dword ptr [ecx]	//moves ecx into edx  (=event)
 00402179  call        dword ptr [edx+24h]	//call into vtable of event
 0040217C  add         esp,20h			//Add 20 to esp ;-) Whatever is there
 0040217F  mov         dword ptr [ebp-4],0	//Move something
 00402186  jmp         +18Ch (40219Ch)		//Jump to 18C after 40218C
 
 
 The interesting line is 0040216D.  It seems something is being pushed 
 onto the stack in between INFINITE and &evCode.  I'm still somewhat of a 
 new programmer, so I don't know exactly what's going on here, but I can 
 hazard a guess that the 0 is an argument that is being mistakenly passed 
 to WaitForCompletiion.  If I step to the offending line and then set the 
 execution to the next line (thereby running every line except the 
 offending line) the code works and evCode is assigned a value.
 
 Clearly something's up.  Any ideas?  I can post the full code of the 
 program if I need to, but there are about 1000 lines between both files.
 
 - Malcolm Sharpe
I don't know what the 0 is for, too. Maybe my comments make it easier to read for the next one. Maybe this is a compiler bug?
Jun 01 2004
parent Malcolm Sharpe <masharpe2000 yahoo.ca> writes:
Stephan Wienczny wrote:
 See Comments
 
 Malcolm Sharpe wrote:
  >
 
 00402169  lea         eax,[evCode]        //Calculates relative 
 address of evCode
 0040216C  push        eax            //pushes that value onto the stack
 0040216D  push        0            //pushes 0 on the stack
 0040216F  push        0FFFFFFFFh        //pushes infinite on the stack
 00402171  push        dword ptr [event]    //pushes event as dword 
 onto stack
 00402174  mov         ecx,dword ptr [event]    //moves event into ecx
 00402177  mov         edx,dword ptr [ecx]    //moves ecx into edx  
 (=event)
 00402179  call        dword ptr [edx+24h]    //call into vtable of event
 0040217C  add         esp,20h            //Add 20 to esp ;-) Whatever 
 is there
 0040217F  mov         dword ptr [ebp-4],0    //Move something
 00402186  jmp         +18Ch (40219Ch)        //Jump to 18C after 40218C


 The interesting line is 0040216D.  It seems something is being pushed 
 onto the stack in between INFINITE and &evCode.  I'm still somewhat of 
 a new programmer, so I don't know exactly what's going on here, but I 
 can hazard a guess that the 0 is an argument that is being mistakenly 
 passed to WaitForCompletiion.  If I step to the offending line and 
 then set the execution to the next line (thereby running every line 
 except the offending line) the code works and evCode is assigned a value.

 Clearly something's up.  Any ideas?  I can post the full code of the 
 program if I need to, but there are about 1000 lines between both files.

 - Malcolm Sharpe
I don't know what the 0 is for, too. Maybe my comments make it easier to read for the next one. Maybe this is a compiler bug?
That's about what I thought that code did. The jmp instruction is there because the method call is at the end of a try block. Maybe the add and mov are there as part of that as well. Here's some more information that might be helpful: if I replace long evCode; event.WaitForCompletion(INFINITE, &evCode); with OAEVENT hEvent; event.GetEventHandle(&hEvent); the event.GetEventHandle(&hEvent); statement produces the disassembly 0040213D lea edx,[hEvent] 00402140 push edx 00402141 push dword ptr [event] 00402144 mov ebx,dword ptr [event] 00402147 mov esi,dword ptr [ebx] 00402149 call dword ptr [esi+1Ch] 0040214C add esp,1Ch 0040214F mov dword ptr [ebp-4],0 00402156 jmp +15Ch (40216Ch) and there is no error. It is also clear that there is no extra argument being passed, unlike in the problem code.
Jun 01 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
The 'extra argument' you see is the hidden 'this' pointer. 'this' points to
the instance of the interface object. But you've set 'event' to null.

"Malcolm Sharpe" <masharpe2000 yahoo.ca> wrote in message
news:c9j781$2r8t$1 digitaldaemon.com...
 I am trying to port a small C++ program using DirectShow to D.  Mostly,
 it has been working fine.  However, one method call has problems with a
 null reference being passed, even though there is no argument.  I'll
 snip out the relevent sections of code (minus some error-checking) to
 clarify:

 // dshow.d

 module dshow;

 ...

 interface IMediaEvent : IDispatch
 {
 extern (Windows):

 ...

 HRESULT WaitForCompletion(long msTimeout, long * pEvCode);

 ...

 }

 ...


 // test.d

 import dshow;

 ...

 IMediaEvent event = null;

 ...

 graph.QueryInterface(&IID_IMediaEvent, cast(void**)(&event));

 ...

 long evCode;
 event.WaitForCompletion(INFINITE, &evCode);

 ...


 The program has an access violation on that last line
 (event.WaitForCompletion).  It turns out it is a null reference problem.
   According to the Visual Studio debugger, this is the disassembly for
 that last line:


 00402169  lea         eax,[evCode]
 0040216C  push        eax
 0040216D  push        0
 0040216F  push        0FFFFFFFFh
 00402171  push        dword ptr [event]
 00402174  mov         ecx,dword ptr [event]
 00402177  mov         edx,dword ptr [ecx]
 00402179  call        dword ptr [edx+24h]
 0040217C  add         esp,20h
 0040217F  mov         dword ptr [ebp-4],0
 00402186  jmp         +18Ch (40219Ch)


 The interesting line is 0040216D.  It seems something is being pushed
 onto the stack in between INFINITE and &evCode.  I'm still somewhat of a
 new programmer, so I don't know exactly what's going on here, but I can
 hazard a guess that the 0 is an argument that is being mistakenly passed
 to WaitForCompletiion.  If I step to the offending line and then set the
 execution to the next line (thereby running every line except the
 offending line) the code works and evCode is assigned a value.

 Clearly something's up.  Any ideas?  I can post the full code of the
 program if I need to, but there are about 1000 lines between both files.

 - Malcolm Sharpe
Jun 04 2004
parent Malcolm Sharpe <masharpe2000 yahoo.ca> writes:
I'm not sure I understand; "push dword ptr [event]" seems to be the 
hidden 'this' pointer, as far as I can tell.  Are you saying that "push 
0" is also a hidden 'this' pointer?  'event' should have a value at that 
point, because of "graph.QueryInterface(&IID_IMediaEvent, 
cast(void**)(&event));", so is there some confusion (maybe because I am 
casting the pointer)?

Walter wrote:
 The 'extra argument' you see is the hidden 'this' pointer. 'this' points to
 the instance of the interface object. But you've set 'event' to null.
 
 "Malcolm Sharpe" <masharpe2000 yahoo.ca> wrote in message
 news:c9j781$2r8t$1 digitaldaemon.com...
 
I am trying to port a small C++ program using DirectShow to D.  Mostly,
it has been working fine.  However, one method call has problems with a
null reference being passed, even though there is no argument.  I'll
snip out the relevent sections of code (minus some error-checking) to
clarify:

// dshow.d

module dshow;

...

interface IMediaEvent : IDispatch
{
extern (Windows):

...

HRESULT WaitForCompletion(long msTimeout, long * pEvCode);

...

}

...


// test.d

import dshow;

...

IMediaEvent event = null;

...

graph.QueryInterface(&IID_IMediaEvent, cast(void**)(&event));

...

long evCode;
event.WaitForCompletion(INFINITE, &evCode);

...


The program has an access violation on that last line
(event.WaitForCompletion).  It turns out it is a null reference problem.
  According to the Visual Studio debugger, this is the disassembly for
that last line:


00402169  lea         eax,[evCode]
0040216C  push        eax
0040216D  push        0
0040216F  push        0FFFFFFFFh
00402171  push        dword ptr [event]
00402174  mov         ecx,dword ptr [event]
00402177  mov         edx,dword ptr [ecx]
00402179  call        dword ptr [edx+24h]
0040217C  add         esp,20h
0040217F  mov         dword ptr [ebp-4],0
00402186  jmp         +18Ch (40219Ch)


The interesting line is 0040216D.  It seems something is being pushed
onto the stack in between INFINITE and &evCode.  I'm still somewhat of a
new programmer, so I don't know exactly what's going on here, but I can
hazard a guess that the 0 is an argument that is being mistakenly passed
to WaitForCompletiion.  If I step to the offending line and then set the
execution to the next line (thereby running every line except the
offending line) the code works and evCode is assigned a value.

Clearly something's up.  Any ideas?  I can post the full code of the
program if I need to, but there are about 1000 lines between both files.

- Malcolm Sharpe
Jun 09 2004