c++ - 进程挂起调试 C/C++

标签 c++ c windbg crash-dumps heap-dump

这里对 windbg 有点陌生

我正在开发一个在其中生成 exe 的应用程序。 我们的应用程序生成一个进程,比如 A.exe,它调用一个 dll aDll.dll,它又调用 BDll.dll

有时进程出现挂起,客户不得不重启应用程序/

Windbg 堆栈跟踪显示以下内容:

 # ChildEBP RetAddr  Args to Child              
00 0012f9ec 77559d8a 0000000c 00280000 00b52b78 ntdll!_SEH_epilog4
01 0012fa34 77526287 00000012 00b52b70 0012fafc ntdll!RtlpCoalesceFreeBlocks+0x84c (FPO: [Non-Fpo])
02 0012fb2c 775265a6 00b3e090 00b3e098 00b3e098 ntdll!RtlpFreeHeap+0x1f4 (FPO: [Non-Fpo])
03 0012fb4c 760bc3c4 00280000 00000000 00b3e098 ntdll!RtlFreeHeap+0x142 (FPO: [Non-Fpo])
04 0012fb60 70393c1b 00280000 00000000 00b3e098 kernel32!HeapFree+0x14 (FPO: [Non-Fpo])
05 0012fbac 00211060 00b3e098 1002082b 0044cf00 msvcr90!free+0xcd (FPO: [Non-Fpo])
06 0012fbb4 1002082b 0044cf00 00282690 0045c5e0 BDll!CdCString::~CdCString(void)+0x10 (FPO: [0,0,0]) (CONV: thiscall) [d:\code\udstring.cpp @ 63]
07 0012fbd0 703523b1 0044cf00 3dc7c9a8 00000000 Adll!CADllClass::~CADllClass(void)+0x4b (FPO: [0,4,0]) (CONV: thiscall) [d:\code\Adll.cpp @ 123]
08 0012fc14 70352496 00000000 00000000 00000001 msvcr90!_cinit+0xf5 (FPO: [Non-Fpo])
09 0012fc24 70352c90 3dc7c9e8 00000001 0012fc7c msvcr90!_cexit+0xb (FPO: [0,0,0])
0a 0012fc54 70352d5e 70330000 00000000 00000001 msvcr90!__p__tzname+0x106 (FPO: [Non-Fpo])
0b 0012fc68 775289d8 70330000 00000000 00000001 msvcr90!_CRTDLL_INIT+0x1e (FPO: [Non-Fpo])
0c 0012fc88 7752e104 70352d40 70330000 00000000 ntdll!LdrpCallInitRoutine+0x14
0d 0012fd2c 7752e19f 002a28b6 703560ad 00000001 ntdll!LdrShutdownProcess+0x1aa (FPO: [Non-Fpo])
0e 0012fd40 760cbbe6 00000000 77e8f3b0 ffffffff ntdll!RtlExitUserProcess+0x74 (FPO: [Non-Fpo])
0f 0012fd54 0040220c 00000000 00462c60 002a28a2 kernel32!ExitProcessStub+0x12 (FPO: [1,0,0])
10 0012fef8 0044c47c 00400000 00000000 002a28a2 AExe!WinMain(struct HINSTANCE__ * hInstance = 0x0040220c, struct HINSTANCE__ * hPrevInstance = 0x00000000, char * lpCmdLine = 0x00462c60 "", int iCmdShow = 0n2762914)+0x2cc (FPO: [4,100,4]) (CONV: stdcall) [d:\code\AExe\AExemain.cpp @ 1165]
11 0012ff88 760bed5c 7ffde000 0012ffd4 775337eb AExe!__tmainCRTStartup(void)+0x140 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 574]
12 0012ff94 775337eb 7ffde000 74f05a38 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])
13 0012ffd4 775337be 0044c65b 7ffde000 00000000 ntdll!__RtlUserThreadStart+0x70 (FPO: [Non-Fpo])
14 0012ffec 00000000 0044c65b 7ffde000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

WinDbg 指向的 AExe 点是: .

                    ExitProcess(GetLastError());
                return 0;
->Line 1161   }
->Line 1162       else
->Line 1163   {
#endif
->Line 1165   if ((lpCmdLine) && (lpCmdLine[0] != '\0'))
          {

ADLL中Windbg指向的点是

-> Line 120  // Free allocated resources
-> Line 121  CleanUp();
-> Line 122
-> Line 123  }                     

WinDbg指向的BDll处的代码是

        CdCString::~CdCString()
        {
-> Line 63         free(m_pData);
        }

在此之上,Windbg 正在转移到 FreeHeap 等 .. 我不明白 数据类型是 char* m_pData;

问题:- 任何人都可以提供更多信息吗?这是堆损坏吗?如果是这样,我怎样才能检测到相同的内容?因为这是一个庞大的程序 ..

我做的一些 Action 是

Action - 1: 在两个 dll 的 DLLMail 和 exe 的 WinMain 的开头我添加了以下代码

{
   _CrtSetDbgFlag (
   _CRTDBG_ALLOC_MEM_DF |
   _CRTDBG_LEAK_CHECK_DF);
   _CrtSetReportMode ( _CRT_ERROR,
   _CRTDBG_MODE_DEBUG);

并做了一个发布构建,希望这会打破堆损坏。除了进程挂起外,我没有看到任何中断。

Action - 2: 另一个操作是我在应用程序验证器上附加了 Aexe.exe 并启用了“基本”

Action - 3: 我做的第三个 Action 是将 gFlag 设置为以下 . C:\Program Files\Windows 调试工具 (x86)>gflags.exe/p 路径:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image 文件执行选项 ADll.dll:使用标志启用的页面堆(跟踪) AExe.exe:使用标志启用的页面堆(完整跟踪) BDll.dll:使用标志启用的页面堆(跟踪) C:\Program Files\Windows 调试工具 (x86)>

但我仍然没有发现任何中断等.........我做了上面的两个步骤,希望代码能够进入内存损坏发生的地方 我做错了什么吗?

这是堆损坏的问题吗?如果是这样,我该如何检测它(exe 或 dll) 如果不是堆损坏,请说明它是什么。

详细信息 平台 此问题已在 64 位中报告,但我能够在 32 位 Windows 中重现。 Arsenal :- 带符号的完整源代码/适用于 Windows 的调试工具/App 验证器

感谢期待。

P.S -我已经更改了实际文件/函数的名称。

-------------- Some more details on the Heap Corruption from Windbg ------
0012f8cc 10309d3c verifier!VerifierStopMessage+0x1f8 (FPO: [Non-Fpo])
0012f930 10306e4d verifier!AVrfpDphReportCorruptedBlock+0x10c (FPO: [Non-Fpo])
0012f994 10306f95 verifier!AVrfpDphFindBusyMemoryNoCheck+0x7d (FPO: [Non-Fpo])
0012f9b8 10307240 verifier!AVrfpDphFindBusyMemory+0x15 (FPO: [Non-Fpo])
0012f9d4 10309080 verifier!AVrfpDphFindBusyMemoryAndRemoveFromBusyList+0x20 (FPO: [Non-Fpo])
0012f9f0 771e6694 verifier!AVrfDebugPageHeapFree+0x90 (FPO: [Non-Fpo])
0012fa38 771aa13e ntdll!RtlDebugFreeHeap+0x2f (FPO: [Non-Fpo])
0012fb2c 771765a6 ntdll!RtlpFreeHeap+0x5d (FPO: [Non-Fpo])
0012fb4c 769ec3c4 ntdll!RtlFreeHeap+0x142 (FPO: [Non-Fpo])
0012fb60 70123c1b kernel32!HeapFree+0x14 (FPO: [Non-Fpo])
0012fbac 01481060 msvcr90!free+0xcd (FPO: [Non-Fpo])
0012fbb4 10020841 BDll!CdCString::~CdCString+0x10 (FPO: [0,0,0]) (CONV: thiscall)     [d:\code\udstring.cpp @ 65]
0012fbd0 700e23b1 ADll!ADllClass::~ADllClass+0x41 (FPO: [0,4,0]) (CONV: thiscall) [d:\code\Adll.cpp @ 123]
0012fc14 700e2496 msvcr90!_cinit+0xf5 (FPO: [Non-Fpo])
0012fc24 700e2c90 msvcr90!_cexit+0xb (FPO: [0,0,0])
0012fc54 700e2d5e msvcr90!__p__tzname+0x106 (FPO: [Non-Fpo])
0012fc68 771789d8 msvcr90!_CRTDLL_INIT+0x1e (FPO: [Non-Fpo])
0012fc88 7717e104 ntdll!LdrpCallInitRoutine+0x14
0012fd2c 7717e19f ntdll!LdrShutdownProcess+0x1aa (FPO: [Non-Fpo])
0012fd40 769fbbe6 ntdll!RtlExitUserProcess+0x74 (FPO: [Non-Fpo])

0:000> !heap -s -v
LFH Key                   : 0x1290358e
Termination on corruption : DISABLED
  Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                (k)     (k)    (k)     (k) length      blocks cont. heap 
-----------------------------------------------------------------------------
.01640000 00000002    1024      4      4      2     1     1    0      0      
.014f0000 00001002     256      4    256      2     1     1    0      0      
.00010000 00008000      64      4     64      2     1     1    0      0      
.01f20000 00001002      64      4     64      2     1     1    0      0      
.014b0000 00001002     256      4    256      2     1     1    0      0      
.024c0000 00001002      64      4     64      2     1     1    0      0      
.025d0000 00001002     256      4    256      2     1     1    0      0      
-----------------------------------------------------------------------------

我被困在这之外...... windbg 指向与我上面所说的相同的 Free 语句。 (虽然行号可能看起来有所改变)

最佳答案

你好 Stack Overflow 成员,

看起来问题已经解决了。问题就在我的脸上。

CdCString::~CdCString()
{
/* The problem */   free(m_pData);
}

我设法通过代码阻止了这个问题

CdCString::~CdCString()
{
    if (m_pData != 0)
    {
       free(m_pData);
       m_pData = 0;
    }
}

dll 挂起不再发生。

注意:- 坦率地说,我对这个修复并不满意,因为我有一种直觉,这个问题存在于 ADll 甚至 AExe 中更深的地方。稍后我将不得不挖掘这个问题。

我学到的一些教训

1 正如 paddy 所建议的,我必须阅读 dll 最佳实践文档

2 当我在我的应用程序中使用应用程序验证程序时 - 它不会崩溃/挂起。但没有它挂起。因此,我使用的另一个最佳工具是调试诊断工具 http://www.microsoft.com/en-us/download/details.aspx?id=26798

  1. Windbg 堆命令在这里帮了大忙。特别是 !heap 等

再次感谢。 (我可能没有这个帐户,因为我也忘记了密码/电子邮件 ID 密码。)

关于c++ - 进程挂起调试 C/C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20381490/

相关文章:

c++ - 使用头文件中的类变量的误解

c - 在 C 中要求用户重复该程序或退出

windbg - 加载 .NET 2 或 .NET 4 时如何设置断点?

c# - 在 Visual Studio 2008 中为 .Net 托管应用程序从 WinDbg 调试 .dmp 文件

c++ - ->second 是否为迭代器 my_map.end() 定义?

c++ - 如何将 .obj 文件包含到项目中

c++ - 如何在 C++ 中逐个字符地从文件中读取?

c - 无需预洗牌即可生成(非常)大的非重复整数序列

java - 在一个项目中将 C++ 与 Java 集成。有可能吗?怎么做?

windbg - 在哪里可以找到 Andrew Richards 为 WinDBG 编写的 pde 扩展?