回调中的Win32 API向量问题
在我的程序的 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”上遇到访问冲突。 “point”和“point_vector”都是全局声明的,并且在调试器中似乎有效。如果我在本地声明它们,则不会发生访问冲突。为什么会出现这种情况呢?
这是VS10上的。
@马丁洛弗尔 这是调用堆栈
msvcr100d.dll!operator delete(void * pUserData=0xfefefefe) 第 52 行 + 0x3 字节 C++ my_app.exe!std::allocator::deallocate(tagPOINT * * _Ptr=0xfefefefe, unsigned 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, unsigned int message=513, unsigned 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(),也会发生这种情况。
In the WndProc callback of my program I'm doing this to store a mouse click in a vector:
case WM_LBUTTONDOWN:
point = new POINT();
point->x = LOWORD (lParam);
point->y = HIWORD (lParam);
point_vector.push_back(point);
InvalidateRect(hWnd, NULL, TRUE);
break;
It compiles fine but when this runs, I get an access violation on the "push_back". Both "point" and "point_vector" are declared globally and seem valid in the debugger. If I declare them locally, no access violation. Why would this happen?
This is on VS10.
@Martyn Lovell
Here is the call stack
msvcr100d.dll!operator delete(void * pUserData=0xfefefefe) Line 52 + 0x3 bytes C++
my_app.exe!std::allocator::deallocate(tagPOINT * * _Ptr=0xfefefefe, unsigned int formal=0) Line 182 + 0x9 bytes C++
my_app.exe!std::vector >::reserve(unsigned int _Count=1) Line 768 C++
my_app.exe!std::vector >::_Reserve(unsigned int _Count=1) Line 1298 C++
my_app.exe!std::vector >::push_back(tagPOINT * const & _Val=0x008e9d58) Line 992 C++
my_app.exe!WndProc(HWND * hWnd=0x000b060a, unsigned int message=513, unsigned int wParam=1, long lParam=19857987) Line 241 C++
user32.dll!774662fa()
[Frames below may be incorrect and/or missing, no symbols loaded for 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) Line 62 + 0xc bytes C++
my_app.exe!__tmainCRTStartup() Line 547 + 0x2c bytes C
my_app.exe!wWinMainCRTStartup() Line 371 C
kernel32.dll!764c33ca()
ntdll.dll!77e79ed2()
ntdll.dll!77e79ea5()
And this is the line where it crashes in dbgdel.cpp (not sure if this is helpful)
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
@CoreyStup
Doesn't seem to make any difference if the vars are local or global
Also this happens if I call other vector functions like resize(), clear() or reserve(), but not size().
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是调用堆栈的顶部:
让我们从头开始检查:
在上面的 1 中,WM_LBUTTONDOWN 到达 WndProc。
在上面的 2 中,您使用指向堆上新创建的 POINT 实例的指针调用 Push_back。
在上面的3中,push_back调用内部函数_Reserve,计数为1,为1个
POINT*
分配内存。这是因为向量是空的,因为尚未添加任何元素,并且该特定向量实例分配器的指数增长方案从 1 开始。(添加另一个元素将重新分配新内存并复制第一个元素加上新元素)在上面的 4 中,_Reserve 将其调用转发给 Reserve 函数。
在上面的 5 中,为第一个
POINT*
分配空间后,reserve 发现内部向量数据指针(在 VS 2010 中它的名称是_Myfirst
)为非空(参见上面的 _Ptr=0xfefefefe),因此在将其指向刚刚分配的新空间之前,必须释放 0 (!) POINT* 元素的旧空间。不幸的是,allocator::deallocate 忽略了要释放 0 个元素(可能是无操作)并愉快地尝试删除 0xfefefefe。
在上面的 6 中,不幸的是 0xfefefefe 是已释放内存的 VS 调试表示,因此删除 chokes。它还能做什么?
很奇怪。
This is the top of the callstack:
Let's examine it from the beginning:
In 1 above, WM_LBUTTONDOWN arrives at WndProc.
In 2 above, you call push_back with a pointer to a newly created POINT instance on the heap.
In 3 above, push_back calls the internal function _Reserve with a count of 1 to allocate memory for 1
POINT*
. This is because the vector is empty, since no element has been added yet, and the exponential growth scheme of this particular vector instance allocator starts with 1. (Adding another element would re-allocate new memory and copy the first element plus the new one there.)In 4 above, _Reserve forwards its call to the reserve function.
In 5 above, after having allocated space for the first
POINT*
, reserve sees that the internal vector data pointer (in VS 2010 it's name is_Myfirst
) is non-null (see _Ptr=0xfefefefe above), so before pointing it at the new space just allocated, the old space of 0 (!)POINT*
elements must be freed.Unfortunately, allocator::deallocate ignores that 0 elements are to be deallocated (could be a no-op) and happily tries to delete 0xfefefefe.
In 6 above, the 0xfefefefe is unfortunately the VS debug representation of already freed memory, so delete chokes. What else can it do?
Strange it is.
好的,解决了。在我的程序的不同部分,我调用:
应该是
这导致了某种内存损坏,因为 msgbuf length != 1024
我真是个混蛋。向大家道歉
OK, solved it. In a different part of my program I was calling:
Should have been
This caused some sort of memory corruption because msgbuf length != 1024
I am such an ass. Apologies to everyone