www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Access violation after inheriting.

reply Zarathustra <adam.chrapkowski gmail.com> writes:
Could somebody explain memory rules in class inheriting?
The following code illustrates my problem, look at 'main' function:
//____________________________________________
module window;

private import base;
private import structs;

private static import user32;
private static import kernel32;
private static import gdi32;

private:
extern (Windows) dword wndProc(ptr o_hwnd, dword o_msg, dword o_wparam, dword
o_lparam){

  alias user32.EWindowMessage WM;
  auto l_wnd = cast(Window*)user32.getWindowLong(o_hwnd, 0x00);
  
  if(o_msg == WM.NCCREATE){
    user32.setWindowLong(o_hwnd, 0x00, *(cast(dword*)o_lparam));
  }
  else if(l_wnd is null){

    return 0x00;
  }
  
  return (cast(Window*)user32.getWindowLong(o_hwnd, 0x00)).wndProc(o_hwnd,
o_msg, o_wparam, o_lparam);
}

public:
class Window{
  private const ptr handle;

  void onMouseDown (MouseEventArgs o_mea){
  }

  this(){
    WINWndClassEx wndClass;

    wndClass.size          = 0x00000030;
    wndClass.style         = 0x00000003;
    wndClass.wndProc       = cast(ptr)&.wndProc;
    wndClass.clsExtraBytes = 0x00000000;
    wndClass.wndExtraBytes = 0x00000004;
    wndClass.hInstance     = kernel32.getModuleHandle(null);
    wndClass.hIcon         = user32.loadIcon(null, 0x00007F00);
    wndClass.hCursor       = user32.loadCursor(null, 0x00007F00);
    wndClass.hbrBackground = gdi32.getStockObject(0x00000000);
    wndClass.menuName      = null;
    wndClass.className     = cast(wstr)"clsname";
    wndClass.hIconSm       = user32.loadIcon(null, 0x00007F00);
    
    if(!user32.registerClassEx(cast(ptr)&wndClass)){
      if(kernel32.getLastError() != 0x0582){
        user32.messageBox(null,
user32.translateErrorCode(kernel32.getLastError()), cast(wstr)"error",
0x00000000);
        assert(false, "window class registering failed");
      }
    }

    handle = user32.createWindowEx(
      0,
      wndClass.className,
      cast(wstr)"<applicationcaption>",
      0x00CF0000,
      0x00000000,
      0x00000000,
      0x00000280,
      0x000001E0,
      null,
      null,
      kernel32.getModuleHandle(null),
      cast(ptr)&this
    );
    
    if(handle is null){
      user32.messageBox(null,
user32.translateErrorCode(kernel32.getLastError()), cast(wstr)"error",
0x00000000);
      assert(false, "window creating failed");
    }
  }

  public void run(){
    WINMsg msg;
    
    user32.showWindow(handle, 0x0000000A);
    user32.updateWindow(handle);

    while(user32.getMessage(cast(ptr)&msg, null, 0, 0)){
      user32.translateMessage(cast(ptr)&msg);
      user32.dispatchMessage(cast(ptr)&msg);
    }
  }

  private dword wndProc(ptr o_hwnd, dword o_msg, dword o_wparam, dword
o_lparam){

    alias user32.EWindowMessage WM;
    alias user32.EMouseKey      WK;

    switch(o_msg){

      case WM.DESTROY:
        user32.postQuitMessage(0x00);
      break;

      case WM.LBUTTONDOWN:
        MouseEventArgs l_mea;
        l_mea.button = MouseButton.LEFT;
        l_mea.location.x = loword(o_lparam);
        l_mea.location.x = hiword(o_lparam);
        onMouseDown(l_mea);
      break;

      case WM.RBUTTONDOWN:
        MouseEventArgs l_mea;
        l_mea.button = MouseButton.RIGHT;
        l_mea.location.x = loword(o_lparam);
        l_mea.location.x = hiword(o_lparam);
        onMouseDown(l_mea);
      break;
      
      default: return user32.defWindowProc(o_hwnd, o_msg, o_wparam, o_lparam);
    }
    return 0;
  }
}
//____________________________________________
module main:
// ...
class MyWindow : Window{
  this(){
    super();
  }

  override void onMouseDown(MouseEventArgs o_mea){
    MsgBox(cast(char[])"Hello");
  }
  
}

void main(){
  
  try{
    Window   wnd   = new   Window();
    MyWindow mywnd = new MyWindow();
    wnd  .run();  // ok
    mywnd.run();  // access violation onClick
  }
  catch(Object o){
    MsgBox(cast(char[])o.toString);
  }
}
//____________________________________________
Oct 19 2009
next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Try compiling with -gc and run it under the debugger.
Oct 19 2009
prev sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Zarathustra wrote:
 Could somebody explain memory rules in class inheriting?
 The following code illustrates my problem, look at 'main' function:

Posts like this belong on d.learn.
 //____________________________________________
 module window;
 
 private import base;
 private import structs;
 
 private static import user32;
 private static import kernel32;
 private static import gdi32;

imports are private by default.
 private:
 extern (Windows) dword wndProc(ptr o_hwnd, dword o_msg, dword o_wparam, dword
o_lparam){
 
   alias user32.EWindowMessage WM;
   auto l_wnd = cast(Window*)user32.getWindowLong(o_hwnd, 0x00);
   
   if(o_msg == WM.NCCREATE){
     user32.setWindowLong(o_hwnd, 0x00, *(cast(dword*)o_lparam));
   }
   else if(l_wnd is null){
 
     return 0x00;
   }
   
   return (cast(Window*)user32.getWindowLong(o_hwnd, 0x00)).wndProc(o_hwnd,
o_msg, o_wparam, o_lparam);
 }

You shouldn't be using Window*: see below.
 public:
 class Window{
   private const ptr handle;
 
   void onMouseDown (MouseEventArgs o_mea){
   }
 
   this(){
     WINWndClassEx wndClass;
 
     wndClass.size          = 0x00000030;
     wndClass.style         = 0x00000003;
     wndClass.wndProc       = cast(ptr)&.wndProc;

What is ptr? If it's void*, you don't need to do this. Incidentally, there's already a set of bindings for the Win32 api. Not sure where the current version is; somewhere on dsource.org.
     wndClass.clsExtraBytes = 0x00000000;
     wndClass.wndExtraBytes = 0x00000004;
     wndClass.hInstance     = kernel32.getModuleHandle(null);
     wndClass.hIcon         = user32.loadIcon(null, 0x00007F00);
     wndClass.hCursor       = user32.loadCursor(null, 0x00007F00);
     wndClass.hbrBackground = gdi32.getStockObject(0x00000000);
     wndClass.menuName      = null;
     wndClass.className     = cast(wstr)"clsname";

Easier to type "clsname"w than cast(wstr)"clsname"
     wndClass.hIconSm       = user32.loadIcon(null, 0x00007F00);
     
     ...
 
     handle = user32.createWindowEx(
       0,
       wndClass.className,
       cast(wstr)"<applicationcaption>",
       0x00CF0000,
       0x00000000,
       0x00000000,
       0x00000280,
       0x000001E0,
       null,
       null,
       kernel32.getModuleHandle(null),
       cast(ptr)&this
     );

this is a reference to the object. &this is the address at which the reference is being stored, which is probably *on the stack*. I wouldn't be surprised if this is why it's segfaulting.
     if(handle is null){
       user32.messageBox(null,
user32.translateErrorCode(kernel32.getLastError()), cast(wstr)"error",
0x00000000);
       assert(false, "window creating failed");
     }
   }
 
   ...
 
 class MyWindow : Window{
   this(){
     super();
   }
 
   override void onMouseDown(MouseEventArgs o_mea){
     MsgBox(cast(char[])"Hello");

Unless MsgBox is defined very strangely, the cast(char[]) here should be superfluous.
   }
   
 }
 
 ...

Oct 19 2009