1

so i just started windows programing with C++. First I draw some lines and it was OK, then i tried to create a class for drawing some shapes, and it's working fine when I'm using a normal method to create object (in the code these parts are commented out), but when I'm using a pointer to create new object, I get an Access violation error.

Here is my class (I've deleted some of the code so it may seems oversimplified at some parts):

class shapes {
public:
   shapes(void);
   void setstartp( POINT& p0);
   void setendp( POINT& p1);

   void draw(HDC hdc);
   ~shapes(void);

   POINT x0;
   POINT x1;
};

shapes::shapes(){}

void shapes::setstartp( POINT& p0){
    x0=p0;
}

void shapes::setendp( POINT& p1){
    x1=p1;
}

void shapes::draw(HDC hdc){
    MoveToEx(hdc,x0.x ,x0.y ,0);
    LineTo(hdc ,x1.x ,x1.y);
}

shapes::~shapes(void) {}

And this is my program, or at least the winproc part:

//shapes sh; 
shapes* sh =0;
bool mousdown =false;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    POINT p0;
    POINT p1;
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
        case WM_LBUTTONDOWN :
            SetCapture(hWnd);
            mousdown = true;

            p0.x = LOWORD(lParam);
            p0.y = HIWORD(lParam);

            // sh.setstartp(p0);
            sh = new shapes();
            sh->setstartp(p0);
            break;    
     case WM_MOUSEMOVE :
         if(mousdown) {
             p1.x = LOWORD(lParam);
             p1.y = HIWORD(lParam);
             // sh.setendp(p1);
            sh->setendp(p1);
            InvalidateRect(hWnd ,0,true);
         }
         break;    
     case WM_LBUTTONUP :
         ReleaseCapture();
         mousdown = false;
         p1.x = LOWORD(lParam);
         p1.y = HIWORD(lParam);

         // sh.setendp(p1);
         sh->setendp(p1);
         InvalidateRect(hWnd ,0,true);
         break;
     case WM_PAINT:
         hdc = BeginPaint(hWnd, &ps);
         // TODO: Add any drawing code here...
         //sh.draw(hdc);
         sh->draw(hdc);
         EndPaint(hWnd, &ps);
         break;
     case WM_COMMAND: 

Here is my Access violation error :

Unhandled exception at 0x00411fda in NEWWIN.exe: 0xC0000005: Access violation reading location 0x00000004.

And error points to class implement :

 void shapes::draw(HDC hdc) {           
     MoveToEx(hdc,x0.x ,x0.y ,0);
     LineTo(hdc ,x1.x ,x1.y);
 }

Apparently there is a problem with my class properties x0 and x1 :

this 0x00000000 {x0={...} x1={...} } shapes * const

x0 {x=??? y=???} tagPOINT

x CXX0030: Error: expression cannot be evaluated

y CXX0030: Error: expression cannot be evaluated

x1 {x=??? y=???} tagPOINT

x CXX0030: Error: expression cannot be evaluated

y CXX0030: Error: expression cannot be evaluated

2
  • Is it your own choice to do win32 development in C++? I'd first prototype in C# and then port back what turned out to be relevant. Commented Jan 26, 2011 at 12:49
  • yeah my goal is to start directx programming . Commented Jan 26, 2011 at 16:22

3 Answers 3

3

The problem is that you don't construct a shapes object until receiving (and handling a WM_LBUTTONDOWN) event. So if any other event (eg. WM_MOUSEMOVE) is handled before, then sh will still be 0.

Besides, note that you have a memory leak here: you call sh = new shapes(); for every WM_LBUTTONDOWN event, without ever deleting previously allocated objects.

I suggest you allocate your shape object in a WM_CREATE handler, and that you delete it in a WM_DESTROY handler.

Sign up to request clarification or add additional context in comments.

4 Comments

thanx the idea is to create different classes to draw different shapes and "shapes" class is a abstract parent for those classes as i said i deleted those parts to get to the bottom of the problem , now user is going to choose the shape from a menu so object should be created on WM_LBUTTONDOWN i think i could use "if (sh != 0)" to check the object on WM_PAINT
Ok - yes, if (sh) { ... } is fine. And I assume you keep a list of shape objects around, and there isn't a memory leak in your actual program.
yeah there's a vector which im going to store my objects or should i say my pointers on it , so do i need to delete "sh" object as well as my vector on the WM_DESTROY ? user may draw 20 lines before closing the window .. do i need to destroy "sh" object after drawing every line or deleting it once on the WM_DESTROY would be enough ?
You need to keep all shape objects around until WM_DESTROY. That's because in WM_PAINT, you should redraw all existing shapes (actually, only the ones that are in the dirty window region). So yes, in WM_DESTROY, loop over all shapes in the vector and call delete on them (or use a smart pointer in the first place). Then delete the vector (if it has been allocated on the heap).
1
 sh->setendp(p1);

Yes, that will go kaboom. You will always get a WM_MOUSEMOVE message before you get a WM_LBUTTONDOWN message. You didn't create the sh object yet. Change

shapes* sh =0;

to

shapes sh;

for a first-order fix.

Comments

0

Just imagine what happens if your program receives the events in this order:

  1. WM_PAINT
  2. WM_MOUSEMOVE
  3. WM_BUTTONDOWN
  4. WM_PAINT
  5. WM_MOUSEMOVE
  6. WM_BUTTONUP
  7. WM_PAINT

The shapes object is not created until event 3. arrives, but you already try to draw a shape in the first event.

The easiest fix to get rid of the crash is to check that sh is not a null-pointer (if (sh != 0) /* use sh */), or to revert back to using a non-pointer.

But there are bigger problems in your code:

  • Currently you have a memory leak, because you create a new shapes object for every WM_BUTTONDOWN event, but you never delete any of them
  • What do you want to draw if you get a WM_PAINT event before both corners of the shape are set? Currently, you draw a line to an unspecified location.

1 Comment

@max: That is the problem with events. They may come in completely unexpected orders. You can only assume event B follows event A if the handler for event B generated that event. And even then there can be other events coming in between.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.