【问题标题】:Viewing call stack for all threads when debugging a multithreaded Windows CE application在调试多线程 Windows CE 应用程序时查看所有线程的调用堆栈
【发布时间】:2014-07-16 00:24:12
【问题描述】:

因此,使用 Visual Studio 2008 为 Windows CE 6.0 平台开发本机 C++ 代码。考虑以下多线程应用程序:

#include "stdafx.h"

void IncrementCounter(int& counter)
{
    if (++counter >= 1000)
    {
        counter = 0;
    }
}

unsigned long ThreadFunction(void* arguments)
{
    int threadCounter = 0;

    while (true)
    {
         Sleep(20);

         IncrementCounter(threadCounter);
    }

    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{

    CreateThread(
                    NULL,       
                    0,          
                    (LPTHREAD_START_ROUTINE)ThreadFunction, 
                    NULL,       
                    0,          
                    NULL        
                 );


    int mainCounter = 0;

    while (true)
    {
        Sleep(20);

        IncrementCounter(mainCounter);
    }

    return 0;
}

当我构建它以在我的 Windows 7 开发人员上运行时。机器并在 counter = 0; 语句上使用断点从 Visual Studio 运行调试会话,执行最终将中断,并且两个线程将显示在“线程”调试窗口中。我可以使用双击或右键单击->“切换到线程”在两个线程之间来回切换,然后查看调用堆栈并浏览源代码并检查符号(对于我的应用程序代码中的调用堆栈帧)两个线程。但是,当我在通过 Windows CE 连接时执行相同操作时。 ActiveSync/WMDC(已经在我们的自定义 CE 6.0 硬件和内部操作系统和 SDK 以及旧的 Windows mobile 5.0 PDA 和库存 MS SDK 上进行了尝试)我可以看到调用堆栈并浏览线程的源代码发生了中断(当前执行点在我的应用程序代码中),但是我没有得到任何对其他线程有用的东西,它当前在内核空间中被阻塞,等待它的睡眠超时。

任何人都知道是否有可能在 Windows CE 上让它更好地工作?我猜这可能与调试器不知道在哪里可以找到 WinCE 内核元素的 .pdb 符号文件有关,或者我是否需要运行调试操作系统?

Windows CE 6 remote debugging. No call stack when pause program 描述了同样的问题,但并未真正提供解决方案

谢谢

理查德

【问题讨论】:

    标签: multithreading windows-ce


    【解决方案1】:

    可能是因为缺少 coredll.dll 的 pdb 文件。如果您正在为您的设备创建图像,您将可以访问此文件,否则我担心它依赖于平台。

    您可以在此处发现此问题在 VS2005 中被认为是设计使然,因此可能与 VS2008 相同:

    http://connect.microsoft.com/VisualStudio/feedback/details/190785/unable-to-debug-windows-mobile-application-that-is-in-a-system-call

    在以下链接中,您可以找到一些使用“未运行的线程”的平台构建器查找调用堆栈的说明

    https://distrinet.cs.kuleuven.be/projects/SEESCOA/internal/workpackages/workpackage6/Task6dot2/ESCE/classes/331.pdf

    由于我只使用 VS 2005,我无法确认它是否有任何帮助。

    如果日志记录不够(如您提供的 SO 链接中所建议的那样),要查找示例中的线程的调用堆栈,我建议使用 GetThreadCallStack 函数。这是一步一步的过程:

    1 - 将以下代码添加到您的项目中:

    typedef struct _CallSnapshotEx {
      DWORD dwReturnAddr;
      DWORD dwFramePtr;
      DWORD dwCurProc;
      DWORD dwParams[4];
    } CallSnapshotEx;
    
    #define STACKSNAP_EXTENDED_INFO 2
    
    DWORD dwGUIThread;
    void DumpGUIThreadCallStack() {
      HINSTANCE hCore = LoadLibrary(_T("coredll.dll"));
      typedef ULONG (*GETTHREADCALLSTACK)(HANDLE hThrd, ULONG dwMaxFrames, LPVOID lpFrames[], DWORD dwFlags,DWORD dwSkip);
      GETTHREADCALLSTACK pGetThreadCallStack = (GETTHREADCALLSTACK)GetProcAddress(hCore, _T("GetThreadCallStack"));
      if ( !pGetThreadCallStack )
        return;
    
      #define MAX_FRAMES 40
      CallSnapshotEx  lpFrames[MAX_FRAMES];
      DWORD dwCnt = pGetThreadCallStack((HANDLE)dwGUIThread, MAX_FRAMES, (void**)lpFrames, STACKSNAP_EXTENDED_INFO, 0);
    
      TCHAR szBuff[64];
      for ( DWORD i = 0; i < dwCnt; ++i ) {
        wsprintf(szBuff, L"[%d] %p\n", i, lpFrames[i].dwReturnAddr);
        OutputDebugString(szBuff);
      }
    }
    

    它将转储到输出窗口调用帧返回地址(示例输出在第 3 点)。

    2 - 在 WinMain 中初始化 dwGUIThread:

    dwGUIThread = GetCurrentThreadId();
    

    3 - 在ThreadFunction 内的实际断点之前执行DumpGUIThreadCallStack();。它将写入类似于以下内容的输出窗口文本:

    [0] 8C04D2C4
    [1] 8C04D34C
    [2] 40026D48
    [3] 000111F4 <--- 1
    [4] 00011BAC <--- 2
    [5] 4003C2DC
    

    1 和 2 是您感兴趣的返回地址,并且您希望找到离它们最近的符号。

    4 - 在调试器内部切换到反汇编模式(右键单击源文件并选择“转到反汇编”)。在此模式下,您将在窗口顶部看到Address: 行。你应该从输出窗口复制粘贴到它的地址,在我的例子中 000111F4 将引导我到以下行:

          while (true)
          {
              Sleep(20);
    000111F0  mov         r0, #0x14 
    000111F4  bl          0001193C  // <--- 1
    
              IncrementCounter(mainCounter);
    

    它告诉你你的 GUI 线程实际上在做什么。


    Visual Studio 调试器允许从即时窗口执行函数,但我无法调用 DumpGUIThreadCallStack,我总是收到“错误:不支持函数评估”。

    要查找帧返回地址的最近符号,您还可以将 .map 文件与 .cod 文件(/FAcs 编译源)一起使用,google 上有一些很好的教程。

    以上示例在 WCE6.0(最终用户)设备上使用 VS 2005 和标准 SDK 5.0 进行了测试。

    【讨论】:

      猜你喜欢
      • 2012-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 1970-01-01
      • 2010-10-11
      • 1970-01-01
      相关资源
      最近更新 更多