Win32 API векторная проблема в обратном вызове - PullRequest
3 голосов
/ 14 июня 2011

В обратном вызове WndProc моей программы я делаю это для сохранения щелчка мыши в векторе:

case WM_LBUTTONDOWN:
    point = new POINT();
    point->x = LOWORD (lParam);
    point->y = HIWORD (lParam);

    point_vector.push_back(point);

    InvalidateRect(hWnd, NULL, TRUE);
    break;

Он компилируется нормально, но когда он запускается, я получаю нарушение прав доступа на "push_back". И "точка", и "точка_вектор" объявлены глобально и кажутся действительными в отладчике. Если я объявлю их локально, нарушения доступа нет. Почему это случилось?

Это на VS10.

@ Мартын Ловелл Вот стек вызовов

msvcr100d.dll! Оператор delete (void * pUserData = 0xfefefefe) Строка 52 + 0x3 байта C ++ my_app.exe! std :: allocator :: deallocate (tagPOINT * * _Ptr = 0xfefefefe, без знака int formal = 0) Строка 182 + 0x9 байт C ++ my_app.exe! std :: vector> :: Reserve (unsigned int _Count = 1) Строка 768 C ++ my_app.exe! std :: vector> :: _ Reserve (unsigned int _Count = 1) Строка 1298 C ++ my_app.exe! std :: vector> :: push_back (tagPOINT * const & _Val = 0x008e9d58) Строка 992 C ++ my_app.exe! WndProc (HWND * hWnd = 0x000b060a, сообщение без знака int = 513, без знака int wParam = 1, long lParam = 19857987) Строка 241 C ++ user32.dll! 774662fa ()
[Указанные ниже кадры могут быть неправильными и / или отсутствующими, символы не загружены для user32.dll]
user32.dll! 77466d3a ()
user32.dll! 77466ce9 ()
user32.dll! 77466e44 ()
user32.dll! 774677c4 ()
user32.dll! 7746788a ()
my_app.exe! wWinMain (HINSTANCE__ * hInstance = 0x00c80000, HINSTANCE__ * hPrevInstance = 0x00000000, wchar_t * lpCmdLine = 0x006c35d2, int nCmdShow = 1) Строка 62 + 0xc байтов C ++ my_app.exe! __tmainCRTStartup () Строка 547 + 0x2c байт C my_app.exe! wWinMainCRTStartup () Строка 371 C kernel32.dll! 764c33ca ()
ntdll.dll! 77e79ed2 ()
ntdll.dll! 77e79ea5 ()

И это строка, в которой происходит сбой в dbgdel.cpp (не уверен, полезно ли это) / * проверить тип блока * / _ASSERTE (_BLOCK_TYPE_IS_VALID (pHead-> nBlockUse));

@ CoreyStup Кажется, нет никакой разницы, если переменные являются локальными или глобальными

Также это происходит, если я вызываю другие векторные функции, такие как resize (), clear () или reserve (), но не size ().

Ответы [ 2 ]

1 голос
/ 15 июня 2011

И "точка", и "точка_вектор" ... кажутся действительными в отладчике.

  • Как вы думаете, по какой мере они действительны? Коллстак подразумевает обратное.
  • Как это выглядит до того, как вы попробуете push_back в первый раз?

Это вершина стека вызовов:

6. msvcr100d.dll!operator delete(void * pUserData=0xfefefefe) Line 52 + 0x3 bytes C++
5. my_app.exe!std::allocator::deallocate(tagPOINT * * _Ptr=0xfefefefe, unsigned int formal=0) Line 182 + 0x9 bytes C++
4. my_app.exe!std::vector >::reserve(unsigned int _Count=1) Line 768 C++
3. my_app.exe!std::vector >::_Reserve(unsigned int _Count=1) Line 1298 C++
2. my_app.exe!std::vector >::push_back(tagPOINT * const & _Val=0x008e9d58) Line 992 C++
1. my_app.exe!WndProc(HWND * hWnd=0x000b060a, unsigned int message=513, unsigned int wParam=1, long lParam=19857987) Line 241 C++

Давайте рассмотрим это с самого начала:

1. my_app.exe!WndProc(HWND * hWnd=0x000b060a, unsigned int message=513, unsigned int wParam=1, long lParam=19857987) Line 241 C++

В 1 выше WM_LBUTTONDOWN прибывает в WndProc.

2. my_app.exe!std::vector >::push_back(tagPOINT * const & _Val=0x008e9d58) Line 992 C++

В 2 выше вы вызываете push_back с указателем на вновь созданный экземпляр POINT в куче.

3. my_app.exe!std::vector >::_Reserve(unsigned int _Count=1) Line 1298 C++

В 3 выше push_back вызывает внутреннюю функцию _Reserve со счетчиком 1, чтобы выделить память для 1 POINT*. Это связано с тем, что вектор пуст, поскольку еще не добавлен ни один элемент, и схема экспоненциального роста этого конкретного распределителя экземпляров вектора начинается с 1. (Добавление другого элемента приведет к перераспределению новой памяти и копированию первого элемента плюс нового есть.)

4. my_app.exe!std::vector >::reserve(unsigned int _Count=1) Line 768 C++

В вышеприведенном 4 _Reserve перенаправляет свой вызов резервной функции.

5. my_app.exe!std::allocator::deallocate(tagPOINT * * _Ptr=0xfefefefe, unsigned int formal=0) Line 182 + 0x9 bytes C++

В 5 выше, после выделения места для первого POINT*, резерв видит, что внутренний указатель векторных данных (в VS 2010 его имя _Myfirst) не равно нулю (см. _Ptr = 0xfefefefe выше), поэтому перед наведением его на только что выделенное пространство, старое пространство 0 (!) POINT* элементов должно быть освобождено.

К сожалению, allocator :: deallocate игнорирует, что 0 элементов должны быть освобождены (может быть нет), и с радостью пытается удалить 0xfefefefe.

6. msvcr100d.dll!operator delete(void * pUserData=0xfefefefe) Line 52 + 0x3 bytes C++

В 6 выше 0xfefefefe, к сожалению, является отладочным представлением VS уже освобожденной памяти, поэтому удалите дроссели. Что еще он может сделать?

  • Но почему внутренний указатель векторных данных 0xfefefefe?
  • Что вы действительно сделали с вектором перед попыткой push_back?
  • Как именно вы объявили вектор?

Странно это.

0 голосов
/ 15 июня 2011

ОК, решил.В другой части моей программы я звонил:

_stprintf_s(msgbuf, 1024, _T("Mouse coordinates: %d %d\0"), mouse.x, mouse.y);

Должно было быть

_stprintf_s(msgbuf, sizeof(msgbuf), _T("Mouse coordinates: %d %d\0"), mouse.x, mouse.y);

Это вызвало некоторое повреждение памяти, потому что длина msgbuf! = 1024

Я такая задница.Извинения всем

...