Reputation: 3736
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
Upvotes: 1
Views: 886
Reputation: 15768
Just imagine what happens if your program receives the events in this order:
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:
shapes
object for every WM_BUTTONDOWN event, but you never delete any of themUpvotes: 0
Reputation: 942197
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.
Upvotes: 1
Reputation: 7468
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.
Upvotes: 3