回调中的Win32 API向量问题

发布于 2024-11-15 07:03:57 字数 1903 浏览 3 评论 0原文

在我的程序的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

疑心病 2024-11-22 07:03:57

“point”和“point_vector”...在调试器中似乎都有效。

  • 您认为以什么标准衡量它们是有效的?调用堆栈暗示着相反的情况。
  • 在你第一次尝试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 中,您使用指向堆上新创建的 POINT 实例的指针调用 Push_back。

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 将其调用转发给 Reserve 函数。

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

在上面的 5 中,为第一个 POINT* 分配空间后,reserve 发现内部向量数据指针(在 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 调试表示,因此删除 chokes。它还能做什么?

  • 但为什么内部向量数据指针是0xfefefefe呢?
  • 在尝试 push_back 之前,您真正对向量做了什么?
  • 你到底是如何声明向量的?

很奇怪。

Both "point" and "point_vector" ... seem valid in the debugger.

  • By what measure do you think they are valid? The callstack implies the opposite.
  • What does it look like before you try to push_back the first time?

This is the top of the callstack:

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++

Let's examine it from the beginning:

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

In 1 above, WM_LBUTTONDOWN arrives at WndProc.

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

In 2 above, you call push_back with a pointer to a newly created POINT instance on the heap.

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

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.)

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

In 4 above, _Reserve forwards its call to the reserve function.

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

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.

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

In 6 above, the 0xfefefefe is unfortunately the VS debug representation of already freed memory, so delete chokes. What else can it do?

  • But why is the internal vector data pointer 0xfefefefe?
  • What did you really do to the vector before trying push_back?
  • Exactly how did you declare the vector?

Strange it is.

恋竹姑娘 2024-11-22 07:03:57

好的,解决了。在我的程序的不同部分,我调用:

_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 length != 1024

我真是个混蛋。向大家道歉

OK, solved it. In a different part of my program I was calling:

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

Should have been

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

This caused some sort of memory corruption because msgbuf length != 1024

I am such an ass. Apologies to everyone

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文