windbg调试死锁,好迷茫,请教

老灰狼 2014-03-24 01:42:27
mfc的一个对话框程序
这是线程的堆栈;
0:009> ~*kb

0 Id: 368.12e0 Suspend: 1 Teb: 7ffdf000 Unfrozen
ChildEBP RetAddr Args to Child
0012fbc4 77d191be 77d2776b 0043e2c8 00000000 ntdll!KiFastSystemCallRet
0012fbec 5f4395f8 0043e2c8 00000000 00000000 USER32!NtUserGetMessage+0xc
0012fc14 5f43219f 0012fedc 012bf754 7ffd7000 MFC42D!CWinThread::PumpMessage+0x30
0012fc50 5f43459f 00000004 0012fedc 012bf754 MFC42D!CWnd::RunModalLoop+0x202
*** WARNING: Unable to verify checksum for RecExtraction.exe
0012fcb0 0040953f 012bf6f2 0043e290 cccccccc MFC42D!CDialog::DoModal+0x191
0012fee8 5f433523 012bf6f2 012bf754 7ffd7000 RecExtraction!CRecExtractionApp::InitInstance+0x81 [G:\Code\vc2012\VSIP\DigitalViewer_V1\RecExtraction\RecExtraction.cpp @ 61]
0012ff08 00437018 00400000 00000000 00141f03 MFC42D!AfxWinMain+0x83
0012ff20 004362e3 00400000 00000000 00141f03 RecExtraction!WinMain+0x18 [appmodul.cpp @ 30]
0012ffc0 7c81776f 012bf6f2 012bf754 7ffd7000 RecExtraction!WinMainCRTStartup+0x1b3 [crtexe.c @ 330]
0012fff0 00000000 00436130 00000000 78746341 kernel32!BaseProcessStart+0x23

1 Id: 368.16b4 Suspend: 1 Teb: 7ffde000 Unfrozen
ChildEBP RetAddr Args to Child
03afff84 7c92df4a 5fe014bc 00000002 03afffac ntdll!KiFastSystemCallRet
03afff88 5fe014bc 00000002 03afffac 00000001 ntdll!ZwWaitForMultipleObjects+0xc
03afffb4 7c80b729 00000000 0012f284 7c92e920 NETAPI32!NetbiosWaiter+0x73
03afffec 00000000 5fe01449 00000000 00000000 kernel32!BaseThreadStart+0x37

2 Id: 368.1238 Suspend: 1 Teb: 7ffdd000 Unfrozen
ChildEBP RetAddr Args to Child
03bffeb0 7c92d21a 7c8023f1 00000000 03bffee4 ntdll!KiFastSystemCallRet
03bffeb4 7c8023f1 00000000 03bffee4 00bd798d ntdll!NtDelayExecution+0xc
03bfff0c 7c802455 000001f4 00000000 005b9048 kernel32!SleepEx+0x61
*** WARNING: Unable to verify checksum for D:\Acc_HRC\Client\NAPI.dll
*** ERROR: Symbol file could not be found. Defaulted to export symbols for D:\Acc_HRC\Client\NAPI.dll -
03bfff1c 005952ab 000001f4 00585107 000001f4 kernel32!Sleep+0xf
WARNING: Stack unwind information not available. Following frames may be wrong.
03bfff24 00585107 000001f4 0012f694 00000000 NAPI!NAPI_JsonCommand+0x376b
03bfffb0 00588869 7c80b729 005b9048 00000000 NAPI+0x15107
03bfffb4 7c80b729 005b9048 00000000 0012f694 NAPI+0x18869
03bfffe0 7c80b72f 00000000 00000000 00000000 kernel32!BaseThreadStart+0x37
03bfffe4 00000000 00000000 00000000 00588860 kernel32!BaseThreadStart+0x3d

3 Id: 368.1048 Suspend: 1 Teb: 7ffdc000 Unfrozen
ChildEBP RetAddr Args to Child
054afea4 7c92df4a 7c809590 00000002 054afed0 ntdll!KiFastSystemCallRet
054afea8 7c809590 00000002 054afed0 00000001 ntdll!ZwWaitForMultipleObjects+0xc
054aff44 77dc8631 00000002 054aff6c 00000000 kernel32!WaitForMultipleObjectsEx+0x12c
054affb4 7c80b729 00000000 00000000 77dc8ae4 ADVAPI32!WmipEventPump+0x230
054affec 00000000 77dc848a 00000000 00000000 kernel32!BaseThreadStart+0x37

4 Id: 368.1494 Suspend: 1 Teb: 7ffdb000 Unfrozen
ChildEBP RetAddr Args to Child
056afe6c 77d191be 77d2776b 03101298 00000000 ntdll!KiFastSystemCallRet
056afe94 5f4395f8 03101298 00000000 00000000 USER32!NtUserGetMessage+0xc
056afebc 5f438d1d 7c96b060 00000053 031011c0 MFC42D!CWinThread::PumpMessage+0x30
056afee0 5f438576 7c96b060 00000053 031011c0 MFC42D!CWinThread::Run+0x82
056aff80 1020c323 0012fb88 7c96b060 00000053 MFC42D!_AfxThreadEntry+0x326
056affb4 7c80b729 031011c0 7c96b060 00000053 MSVCRTD!_beginthreadex+0x133
056affec 00000000 1020c2b0 031011c0 00000000 kernel32!BaseThreadStart+0x37

5 Id: 368.ec4 Suspend: 1 Teb: 7ffda000 Unfrozen
ChildEBP RetAddr Args to Child
057bff04 7c92df4a 76b2aee9 00000002 057bff6c ntdll!KiFastSystemCallRet
057bff08 76b2aee9 00000002 057bff6c 00000001 ntdll!ZwWaitForMultipleObjects+0xc
057bffb4 7c80b729 00000000 fefefefe fefefefe WINMM!timeThread+0x3a
057bffec 00000000 76b2aeaf 00000000 00000000 kernel32!BaseThreadStart+0x37

6 Id: 368.1124 Suspend: 1 Teb: 7ffd9000 Unfrozen
ChildEBP RetAddr Args to Child
0590ff10 7c92d21a 7c8023f1 00000000 0590ff44 ntdll!KiFastSystemCallRet
0590ff14 7c8023f1 00000000 0590ff44 057f0608 ntdll!NtDelayExecution+0xc
0590ff6c 7c802455 000003e8 00000000 0590ffec kernel32!SleepEx+0x61
*** WARNING: Unable to verify checksum for D:\Acc_HRC\Client\udtapi.dll
*** ERROR: Symbol file could not be found. Defaulted to export symbols for D:\Acc_HRC\Client\udtapi.dll -
0590ff7c 057c9dcb 000003e8 057c7aa9 000003e8 kernel32!Sleep+0xf
WARNING: Stack unwind information not available. Following frames may be wrong.
0590ffec 00000000 057c7a80 057e9178 00000000 udtapi+0x9dcb

7 Id: 368.1578 Suspend: 1 Teb: 7ffd8000 Unfrozen
ChildEBP RetAddr Args to Child
0604fd80 7c92d21a 7c8023f1 00000000 0604fdb4 ntdll!KiFastSystemCallRet
0604fd84 7c8023f1 00000000 0604fdb4 0604fedc ntdll!NtDelayExecution+0xc
0604fddc 7c802455 00000064 00000000 0604fedc kernel32!SleepEx+0x61
0604fdec 0040a5c4 00000064 ffffffff 77d2b326 kernel32!Sleep+0xf
0604fedc 5f438514 0012fd30 ffffffff 77d2b326 RecExtraction!CRecExtractionModule::ThreadDecode+0x164 [G:\Code\vc2012\VSIP\DigitalViewer_V1\RecExtraction\RecExtractionModule.cpp @ 61]
0604ff80 1020c323 0012f4f4 ffffffff 77d2b326 MFC42D!_AfxThreadEntry+0x2c4
0604ffb4 7c80b729 03102240 ffffffff 77d2b326 MSVCRTD!_beginthreadex+0x133
0604ffec 00000000 1020c2b0 03102240 00000000 kernel32!BaseThreadStart+0x37

8 Id: 368.bd4 Suspend: 1 Teb: 7ffd6000 Unfrozen
ChildEBP RetAddr Args to Child
0614fd4c 7c92df5a 7c939b23 00000604 00000000 ntdll!KiFastSystemCallRet
0614fd50 7c939b23 00000604 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
0614fdd8 7c921046 0012fe08 5f401b5f 0012fe08 ntdll!RtlpWaitForCriticalSection+0x132
0614fde0 5f401b5f 0012fe08 0012fdfc 0614fedc ntdll!RtlEnterCriticalSection+0x46
0614fdf0 0040b207 ffffffff 77d2b326 03103ee0 MFC42D!CCriticalSection::Lock+0x14
0614fedc 5f438514 0012fd30 ffffffff 77d2b326 RecExtraction!CRecExtractionModule::ThreadAnalysis+0x185 [G:\Code\vc2012\VSIP\DigitalViewer_V1\RecExtraction\RecExtractionModule.cpp @ 331]
0614ff80 1020c323 0012f4f4 ffffffff 77d2b326 MFC42D!_AfxThreadEntry+0x2c4
0614ffb4 7c80b729 03103ee0 ffffffff 77d2b326 MSVCRTD!_beginthreadex+0x133
0614ffec 00000000 1020c2b0 03103ee0 00000000 kernel32!BaseThreadStart+0x37

# 9 Id: 368.1364 Suspend: 1 Teb: 7ffd5000 Unfrozen
ChildEBP RetAddr Args to Child
0615ffc8 7c972119 00000005 00000004 00000001 ntdll!DbgBreakPoint
0615fff4 00000000 00000000 00000000 00000000 ntdll!DbgUiRemoteBreakin+0x2d


我想知道,
1,怎么能判断这些线程哪个是我想要找的呢?只能通过他的堆栈调用来看么?
2,程序有死锁,怎么看哪个线程在占用这个锁,哪个线程想要得到锁?
...全文
514 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
老灰狼 2014-03-24
  • 打赏
  • 举报
回复
引用 8 楼 zhuobattle 的回复:
!handle 68 f [quote=引用 6 楼 zhuobattle 的回复:] 你的理解基本正确, 0614fd4c 7c92df5a 7c939b23 00000604 00000000 ntdll!KiFastSystemCallRet 0614fd50 7c939b23 00000604 00000000 00000000 ntdll!NtWaitForSingleObject+0xc 0614fdd8 7c921046 0012fe08 5f401b5f 0012fe08 ntdll!RtlpWaitForCriticalSection+0x132 这里的第一个是ebp,第二个是返回函数地址,接下来才是你的参数。 具体要看handle是多少,要看下比如 ntdll!NtWaitForSingleObject参数定义:

NTSTATUS WINAPI NtWaitForSingleObject(
  _In_  HANDLE Handle,
  _In_  BOOLEAN Alertable,
  _In_  PLARGE_INTEGER Timeout
);
这三个 00000604 00000000 00000000分别对应上面的Handle,Alrtable,Timeout. 可见这里的handle值是0x00000604,其它函数参数也是以此类推,具体如果参数比较多时,可以直接打印那个esp来查看 堆栈里的内容。
!handle 604 f 看下handle详细信息 [/quote] 这下就明白了,再次感谢
zhuobattle 2014-03-24
  • 打赏
  • 举报
回复
!handle 68 f
引用 6 楼 zhuobattle 的回复:
你的理解基本正确, 0614fd4c 7c92df5a 7c939b23 00000604 00000000 ntdll!KiFastSystemCallRet 0614fd50 7c939b23 00000604 00000000 00000000 ntdll!NtWaitForSingleObject+0xc 0614fdd8 7c921046 0012fe08 5f401b5f 0012fe08 ntdll!RtlpWaitForCriticalSection+0x132 这里的第一个是ebp,第二个是返回函数地址,接下来才是你的参数。 具体要看handle是多少,要看下比如 ntdll!NtWaitForSingleObject参数定义:

NTSTATUS WINAPI NtWaitForSingleObject(
  _In_  HANDLE Handle,
  _In_  BOOLEAN Alertable,
  _In_  PLARGE_INTEGER Timeout
);
这三个 00000604 00000000 00000000分别对应上面的Handle,Alrtable,Timeout. 可见这里的handle值是0x00000604,其它函数参数也是以此类推,具体如果参数比较多时,可以直接打印那个esp来查看 堆栈里的内容。
!handle 604 f 看下handle详细信息
zhuobattle 2014-03-24
  • 打赏
  • 举报
回复
!locks 在windbg下输入这个命令看下,可显示各线程的锁资源使用情况
zhuobattle 2014-03-24
  • 打赏
  • 举报
回复
你的理解基本正确, 0614fd4c 7c92df5a 7c939b23 00000604 00000000 ntdll!KiFastSystemCallRet 0614fd50 7c939b23 00000604 00000000 00000000 ntdll!NtWaitForSingleObject+0xc 0614fdd8 7c921046 0012fe08 5f401b5f 0012fe08 ntdll!RtlpWaitForCriticalSection+0x132 这里的第一个是ebp,第二个是返回函数地址,接下来才是你的参数。 具体要看handle是多少,要看下比如 ntdll!NtWaitForSingleObject参数定义:

NTSTATUS WINAPI NtWaitForSingleObject(
  _In_  HANDLE Handle,
  _In_  BOOLEAN Alertable,
  _In_  PLARGE_INTEGER Timeout
);
这三个 00000604 00000000 00000000分别对应上面的Handle,Alrtable,Timeout. 可见这里的handle值是0x00000604,其它函数参数也是以此类推,具体如果参数比较多时,可以直接打印那个esp来查看 堆栈里的内容。
赵4老师 2014-03-24
  • 打赏
  • 举报
回复
有时不将“调用函数名字+各参数值,进入函数后各参数值,中间变量值,退出函数前准备返回的值,返回函数到调用处后函数名字+各参数值+返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的,包括捕获各种异常、写日志到屏幕、单步或设断点或生成core文件、……这些方法都不行! 写日志到文件参考下面:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
    #include <windows.h>
    #include <io.h>
#else
    #include <unistd.h>
    #include <sys/time.h>
    #include <pthread.h>
    #define  CRITICAL_SECTION   pthread_mutex_t
    #define  _vsnprintf         vsnprintf
#endif
//Log{
#define MAXLOGSIZE 20000000
#define MAXLINSIZE 16000
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
static char logstr[MAXLINSIZE+1];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef WIN32
void Lock(CRITICAL_SECTION *l) {
    EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
    LeaveCriticalSection(l);
}
#else
void Lock(CRITICAL_SECTION *l) {
    pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
    pthread_mutex_unlock(l);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
    struct tm *now;
    struct timeb tb;

    if (NULL==pszFmt||0==pszFmt[0]) return;
    _vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);
    ftime(&tb);
    now=localtime(&tb.time);
    sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
    sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );
    sprintf(mss,"%03d",tb.millitm);
    printf("%s %s.%s %s",datestr,timestr,mss,logstr);
    flog=fopen(logfilename1,"a");
    if (NULL!=flog) {
        fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
        if (ftell(flog)>MAXLOGSIZE) {
            fclose(flog);
            if (rename(logfilename1,logfilename2)) {
                remove(logfilename2);
                rename(logfilename1,logfilename2);
            }
        } else {
            fclose(flog);
        }
    }
}
void Log(const char *pszFmt,...) {
    va_list argp;

    Lock(&cs_log);
    va_start(argp,pszFmt);
    LogV(pszFmt,argp);
    va_end(argp);
    Unlock(&cs_log);
}
//Log}
int main(int argc,char * argv[]) {
    int i;
#ifdef WIN32
    InitializeCriticalSection(&cs_log);
#else
    pthread_mutex_init(&cs_log,NULL);
#endif
    for (i=0;i<10000;i++) {
        Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);
    }
#ifdef WIN32
    DeleteCriticalSection(&cs_log);
#else
    pthread_mutex_destroy(&cs_log);
#endif
    return 0;
}
//1-78行添加到你带main的.c或.cpp的那个文件的最前面
//81-85行添加到你的main函数开头
//89-93行添加到你的main函数结束前
//在要写LOG的地方仿照第87行的写法写LOG到文件MyLog1.log中
老灰狼 2014-03-24
  • 打赏
  • 举报
回复
哦 每行前面是五个数值
老灰狼 2014-03-24
  • 打赏
  • 举报
回复
引用 2 楼 zhuobattle 的回复:
每个线程对应的堆栈有以下一个id, Id: 368.bd4 其中368是进程pid,后面的bd4就是线程id,注意这里都是十六进制的值。 你要看哪个线程卡住了,可以看堆栈,应该是bd4这个线程在试图进入 CCriticalSection时,调用lock,但是发现是锁住的,所以它就开始等待, 从现象来看,应该是其它线程占用了锁; 也有可能是有线程拿到锁后,执行完退出,但却没有释放锁。
十分感谢,根据你的说法如下堆栈的话; 8 Id: 368.bd4 Suspend: 1 Teb: 7ffd6000 Unfrozen ChildEBP RetAddr Args to Child 0614fd4c 7c92df5a 7c939b23 00000604 00000000 ntdll!KiFastSystemCallRet 0614fd50 7c939b23 00000604 00000000 00000000 ntdll!NtWaitForSingleObject+0xc 0614fdd8 7c921046 0012fe08 5f401b5f 0012fe08 ntdll!RtlpWaitForCriticalSection+0x132 0614fde0 5f401b5f 0012fe08 0012fdfc 0614fedc ntdll!RtlEnterCriticalSection+0x46 0614fdf0 0040b207 ffffffff 77d2b326 03103ee0 MFC42D!CCriticalSection::Lock+0x14 0614fedc 5f438514 0012fd30 ffffffff 77d2b326 RecExtraction!CRecExtractionModule::ThreadAnalysis+0x185 [G:\Code\vc2012\VSIP\DigitalViewer_V1\RecExtraction\RecExtractionModule.cpp @ 331] 0614ff80 1020c323 0012f4f4 ffffffff 77d2b326 MFC42D!_AfxThreadEntry+0x2c4 0614ffb4 7c80b729 03103ee0 ffffffff 77d2b326 MSVCRTD!_beginthreadex+0x133 0614ffec 00000000 1020c2b0 03103ee0 00000000 kernel32!BaseThreadStart+0x37 这里的栈低是下面的,我理解的对么? 程序转到MFC42D!CCriticalSection::Lock+0x14后(这个应该是临界区这个类的lock方法) 执行ntdll!RtlEnterCriticalSection+0x46试图获取锁;但是发现已经被其他线程占用了(这应该是lock内部调用的底层方法) 所以才会ntdll!NtWaitForSingleObject+0xc等待锁 栈顶的函数貌似跟系统内核有关系了 再请教一下,怎么看这个等待的线程要获取的锁的句柄是多少呢? 我看有的文章是用的 0614fdd8 7c921046 0012fe08 5f401b5f 0012fe08 ntdll!RtlpWaitForCriticalSection+0x132 0614fde0 5f401b5f 0012fe08 0012fdfc 0614fedc ntdll!RtlEnterCriticalSection+0x46 这两行中的其中一个;好像是0012fe08这个,但是我不知道,是哪一行的0012fe08; 再个就是每行前面的这四个数字代表什么意思; 前两个我只能猜测是函数理想的入口地址和实际入口地址,但是又觉得十分不靠谱; 麻烦老师了
zhuobattle 2014-03-24
  • 打赏
  • 举报
回复
每个线程对应的堆栈有以下一个id, Id: 368.bd4 其中368是进程pid,后面的bd4就是线程id,注意这里都是十六进制的值。 你要看哪个线程卡住了,可以看堆栈,应该是bd4这个线程在试图进入 CCriticalSection时,调用lock,但是发现是锁住的,所以它就开始等待, 从现象来看,应该是其它线程占用了锁; 也有可能是有线程拿到锁后,执行完退出,但却没有释放锁。
老灰狼 2014-03-24
  • 打赏
  • 举报
回复
忘记说了,锁是CCriticalSection

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧