Ошибка нарушения доступа при использовании указателя на созданный объект - PullRequest
1 голос
/ 26 января 2011

, поэтому я только начал программировать Windows на C ++.Сначала я нарисовал несколько линий, и это было нормально, затем я попытался создать класс для рисования некоторых фигур, и он работает нормально, когда я использую обычный метод для создания объекта (в коде эти части закомментированы), но когдаЯ использую указатель для создания нового объекта, я получаю ошибку Access violation.

Вот мой класс (я удалил часть кода, поэтому он может показаться слишком упрощенным в некоторых частях):

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) {}

И это моя программа,или хотя бы часть winproc:

//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: 

Вот моя Access violation ошибка:

Необработанное исключение в 0x00411fda в NEWWIN.exe: 0xC0000005: Доступнарушение чтения местоположения 0x00000004.

И ошибки указывают на реализацию класса:

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

Видимо, есть проблема с моими свойствами класса x0 и x1:

это 0x00000000 {x0 = {...} x1 = {...}} формы * const

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

x CXX0030: Ошибка: выражение не может быть оценено

y CXX0030: Ошибка: выражение не может быть оценено

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

x CXX0030: Ошибка: выражение не может быть оценено

y CXX0030: Ошибка: выражение не может быть оценено

Ответы [ 3 ]

3 голосов
/ 26 января 2011

Проблема в том, что вы не создаете объект shapes до получения (и обработки WM_LBUTTONDOWN) события. Таким образом, если любое другое событие (например, WM_MOUSEMOVE) было обработано ранее, тогда sh все равно будет равно 0.

Кроме того, обратите внимание, что у вас есть утечка памяти: вы вызываете sh = new shapes(); для каждого WM_LBUTTONDOWN события, не удаляя ранее выделенные объекты.

Я предлагаю вам выделить shape объект в обработчике WM_CREATE, а вы delete - в обработчике WM_DESTROY.

1 голос
/ 26 января 2011
 sh->setendp(p1);

Да, это пойдет kaboom.Вы всегда получите сообщение WM_MOUSEMOVE, прежде чем получите сообщение WM_LBUTTONDOWN.Вы еще не создали объект sh .Измените

shapes* sh =0;

на

shapes sh;

для исправления первого порядка.

0 голосов
/ 26 января 2011

Только представьте, что произойдет, если ваша программа получит события в следующем порядке:

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

Объект shapes не создается до наступления события 3. Но вы уже пытаетесь нарисовать фигуру в первом событии.

Самый простой способ избавиться от сбоя - проверить, что sh не является нулевым указателем (if (sh != 0) /* use sh */), или вернуться к использованию не указателя.

Но в вашем коде есть большие проблемы:

  • В настоящее время у вас есть утечка памяти, потому что вы создаете новый объект shapes для каждого события WM_BUTTONDOWN, но вы никогда не удаляете ни одно из них
  • Что вы хотите нарисовать, если вы получаете событие WM_PAINT до того, как установлены оба угла фигуры? В настоящее время вы рисуете линию в неуказанном месте.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...