HeapAlloc引起的死锁

来源:互联网 发布:中国网络审查 编辑:程序博客网 时间:2024/04/28 13:39

HeapAlloc引起的死锁

2011年10月10日代码疯子发表评论阅读评论

在《Windows高级调试》一书中提到了HeapAlloc有可能造成死锁的一种情况:主线程创建一个工作者线程,在工作者线程中使用HeapAlloc在进程的默认堆上分配一块内存,这时候在主线程中调用TerminateThread结束工作者线程,同时在主线程中使用HeapAlloc来在进程的默认堆上分配一块内存,这时候有可能死锁。

但是这样的情况是非常少见的,书中也提到了。书中提到RtlAllocateHeap会试图进入一个临界区。查阅MSDN对HeapAlloc的解释,可以看到如下一段:

Serialization ensures mutual exclusion when two or more threads attempt to simultaneously allocate or free blocks from the same heap. There is a small performance cost to serialization, but it must be used whenever multiple threads allocate and free memory from the same heap. Setting the HEAP_NO_SERIALIZE value eliminates mutual exclusion on the heap. Without serialization, two or more threads that use the same heap handle might attempt to allocate or free memory simultaneously, likely causing corruption in the heap. The HEAP_NO_SERIALIZE value can, therefore, be safely used only in the following situations:

  • The process has only one thread.
  • The process has multiple threads, but only one thread calls the heap functions for a specific heap.
  • The process has multiple threads, and the application provides its own mechanism for mutual exclusion to a specific heap.

文章开头所提到的情况正好体现出来了:多个线程在同一个堆上进行内存分配。如果工作者线程进入HeapAlloc并获得一个锁,在释放锁之前遭到TerminateThread施暴,那么锁很可能就不会释放;而在主线程中想要在这个堆上分配内存,那么永远也等不到锁而无法进入,导致死锁的产生。

附:《Windows高级调试》提供的示例代码(该死锁情况很难重现)

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
#include <windows.h>#include <stdio.h>#include <conio.h>  DWORD WINAPI ThreadProc( LPVOID lpParam ) {     BYTE* pData=NULL;    for(;;)    {        pData=new BYTE[10000];        //        // Use memory        //        delete[] pData;    }     wprintf(L"Exiting thread\n");    return 1;} void __cdecl wmain ( ){    DWORD dwId=0;    HANDLE hThread=NULL;     hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, &dwId);    if(hThread)    {        BYTE* pData=NULL;        Sleep(500);         wprintf(L"Terminating worker thread...\n");        TerminateThread(hThread, 0);         pData=new BYTE[10000];        if(pData)        {            //            // Use memory            //            delete[] pData;        }        WaitForSingleObject(hThread, INFINITE);        CloseHandle(hThread);    }}
原创文章,转载请注明:
原创粉丝点击