_beginthreadex 内存不足

发布于 2024-08-11 20:05:08 字数 857 浏览 7 评论 0原文

我目前正在调试一个多线程应用程序,该应用程序运行时没有错误,直到某些函数被调用大约 2000 次。之后应用程序停止响应,我可以追踪到 _beginthreadex 因内存不足错误而失败。

在 ProcessExplorer 中检查应用程序时,我可以看到泄漏的线程句柄数量不断增加,虚拟内存不断增加,直到错误发生为止,专用字节保持较低水平。 泄漏的线程也调用 CoInitialize,但从不调用 CoUninitialize。

我想知道的是:

  • 虚拟内存代表什么?
  • 虚拟内存与泄漏的线程句柄有关吗?
  • COM 或 MSXML6(由线程调用)是否复制线程句柄以及如何关闭它们?

我希望我的问题很清楚并且不会违反任何规则,这是我的第一个问题,英语不是我的母语。:-(

我忘了提及,一旦线程终止,我就会关闭 _beginthreadex 返回的句柄,这会将打开的句柄数量减少大约一半,但不会影响虚拟内存。 此外,在我插入 CloseHandle 调用之前,ProcessExplorer 中显示的每个线程句柄的线程句柄计数均为 2。

编辑

我之前因为没有包括这一点而感到愚蠢,我知道线程退出是因为在使用 Visual Studio 进行调试时活动线程的数量不会增加。我确实希望并非所有泄漏的内存都是调用的结果 TerminateThread 因为它们在一个相当大的库中使用,我宁愿不修改它。

对于我的问题的 com 部分,使用 !htrace -diff 我发现由 msxml 分配但在函数调用结束后未释放的线程句柄,它们可能与泄漏有关还是稍后会被关闭?

感谢所有这些评论,虽然问题仍然存在,但它们帮助我更好地理解了它。

I currently debug a multi threaded application, which runs without errors until some functions where called about 2000 times. After that the application stops responding, which I could track down to _beginthreadex failing with an out of memory error.

When examining the Application in ProcessExplorer I can see a growing number of thread handles leaked and a growing virtual memory until the error occurs, the private bytes stay low.
The leaked threads also call CoInitialize and never call CoUninitialize.

What I would like to know is:

  • What does the Virtual memory represent ?
  • Is the virtual memory related to the leaked thread handles?
  • Does COM or MSXML6 (called by the threads) copy thread handles and how can I Close them?

I hope that my question is clear and doesn't break any roules,it is my first question and english isn't my first language.:-(

I forgot to mention, I close the handles returned by _beginthreadex once the threads get terminated, which reduces the number of open handles by about half but does not affect the virtual memory.
Additionally before i inserted the CloseHandle call each thread handle shown in ProcessExplorer had a handle count of two for the thread.

Edit

I fell stupid for not including this before, I know that the threads exit as the number of active threads while debugging with visual studio does not grow. And I do hope that not all of the leaked memory is a result of calls
to TerminateThread as they are used in a rather big library and I would prefer not modifying that.

To the com part of my question, with !htrace -diff i find thread handles allocated by msxml but not freed after the functioncalls end, could they be related to the leak or will they be Closed at a later time?

Thanks for all those comments, while the problem is still there they helped me understand it better.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

夏末染殇 2024-08-18 20:05:08

进程可用的虚拟内存是 4Gb 地址空间中的 2Gb。每个线程默认为其堆栈空间保留大约 1Mb 的虚拟内存空间。因此,在虚拟内存耗尽之前,win32 应用程序的活动线程数量限制为大约 2000 个。

虚拟内存是应用程序在现代虚拟内存操作系统(如 Windows)中获得的内存。在 Win32 上发生的情况是,您的应用程序获得 2Gb 的虚拟地址空间。当您的程序调用 new 或 malloc 时,经过几层隧道后,会在磁盘上(在页面文件中)为您的应用程序分配空间。当 CPU 指令尝试访问该内存时,会抛出硬件异常,内核会将物理 RAM 分配给该区域,并从页面文件中读取内容。
因此,无论 PC 中的物理 RAM 有多少,每个应用程序都认为它可以访问整个 2Gb。
虚拟内存是对 2Gb 空间已使用量的计数。

每个线程(见上文)保留 1 Mb 虚拟地址空间以供其堆栈增长。这 1Mb 中的大部分只是保留空间(希望如此),没有 RAM 或页面文件的支持。

当您关闭线程句柄时,您并没有关闭该线程。线程由另一个线程调用 TerminateThread(这会泄漏线程堆栈和其他一些资源,因此永远不要使用它)、调用 ExitThread() 本身或从其 ThreadProc 退出来终止。

因此,由于 2000 个调用限制、不匹配的 CoInitialize 和 CoUninitialize 调用,我想说您的线程没有完全退出或根本没有退出。 2000 个工作线程中的每一个都陷入困境,而不是在完成工作后退出。

The virtual memory available to a process is 2Gb of the 4Gb address space. Each Thread reserves about 1Mb of virtual memory space by default for its stack space. win32 applications therefore have a limit of about 2000 live threads before virtual memory becomes exhausted.

Virtual memory is the memory that applications get in modern virtual memory OS's like windows. What happens on Win32 is, your application gets given a 2Gb virtual address space. When your program calls new or malloc, after tunneling trhough several layers, space gets allocated for your application ON DISK - in the pagefile. When CPU instructions try to access that memory, hardware exceptions get thrown and the kernel allocates physical RAM to that area, and reads the contents from the pagefile.
So, regardless of the physical RAM in the PC, each and every application believes it has access to a whole 2Gb.
Virtual Memory is a count of how much of your 2Gb space has been used up.

Each thread (see above) reserves 1 Mb of virtual address space for its stack to grow. Most of that 1Mb is just reserved space (hopefully) without the backing of RAM or pagefile.

When you close a thread handle you do NOT close the thread. threads are terminated by another thread calling TerminateThread (which leaks the threads stack and some other resources so NEVER use it), calling ExitThread() themselves, or by exiting from their ThreadProc.

So, with the 2000 call limit, the unmatched CoInitialize and CoUninitialize calls, I would say that your threads are not exiting cleanly or at all. Each of the 2000 worker threads is stuck doing something rather than exiting after finishing their work.

無心 2024-08-18 20:05:08

_beginthreadex/_endthreadex 函数不会自动关闭线程句柄,因此必须调用 win32 CloseHandle 函数来关闭它。句柄是 _beginthreadex 返回的值。如果您使用 _beginthread/_endthread 代替,句柄将自动关闭。

关于虚拟内存:它表示已保留但不一定尚未使用的内存。泄漏的内存(或至少部分)与句柄泄漏有关。当线程的最后一个句柄关闭时,Windows 将释放为其保留的虚拟内存。

The _beginthreadex/_endthreadex functions do not automatically close the thread handle, so you must call the win32 CloseHandle function to close it. The handle is the value returned by _beginthreadex. If you use _beginthread/_endthread instead, the handle will be closed automatically.

Regarding virtual memory: It represents memory that was reserved, but is not necessarily used yet. The leaked memory (or at least part of it) is related to the handle leak. When the last handle to a thread is closed, Windows will release the virtual memory reserved for it.

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