Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 调试器到底做什么?_C++_Visual Studio_Debugging - Fatal编程技术网

C++ 调试器到底做什么?

C++ 调试器到底做什么?,c++,visual-studio,debugging,C++,Visual Studio,Debugging,我偶然发现了一个非常有趣的问题,我的应用程序中的一个函数(必须处理Windows剪贴板)只有在函数中遇到断点时才能正常工作。这让我想知道,当调试器遇到断点时(VS2008,C++)到底做了什么 调试器本质上允许您逐步检查源代码并检查代码的工作方式。如果设置断点并在调试模式下运行,代码将在该断点处暂停,并允许您单步执行代码。这有一些明显的优势。首先,您可以查看内存中变量的状态。其次,它允许您确保您的代码执行您期望它执行的操作,而无需执行大量的打印语句。第三,它让你确保逻辑按照你期望的方式运行 编辑

我偶然发现了一个非常有趣的问题,我的应用程序中的一个函数(必须处理Windows剪贴板)只有在函数中遇到断点时才能正常工作。这让我想知道,当调试器遇到断点时(VS2008,C++)到底做了什么

调试器本质上允许您逐步检查源代码并检查代码的工作方式。如果设置断点并在调试模式下运行,代码将在该断点处暂停,并允许您单步执行代码。这有一些明显的优势。首先,您可以查看内存中变量的状态。其次,它允许您确保您的代码执行您期望它执行的操作,而无需执行大量的打印语句。第三,它让你确保逻辑按照你期望的方式运行

编辑:调试器是我的开发工具箱中最有价值的工具之一,我建议您学习并理解如何使用该工具改进开发过程


我建议您阅读维基百科的文章以了解更多信息。

您的应用程序只有在遇到断点时才能正常工作的原因可能是您的一些手表在以前的调试会话中的手表列表中仍然有副作用。当您到达断点时,手表将被执行,您的程序将以不同的方式运行。

它将停止进程(正在调试的进程)的程序计数器,并显示变量的当前值,并使用当前变量的值来计算表达式

您必须考虑到,如果在遇到断点时编辑某个变量值,那么您正在更改进程状态,因此它的行为可能会有所不同


调试是可能的,因为编译器将调试信息(如函数名、变量名等)插入到可执行文件中。不包含此信息是可能的。

调试器只会在遇到断点时停止程序的执行。如果您的程序在遇到断点时工作正常,但在没有断点的情况下无法工作,这将向我表明您的代码中存在争用条件或其他线程问题。断点正在停止代码的执行,可能允许另一个进程正常完成?

这可能是计时/线程同步问题。你在程序中做过多媒体或多线程处理吗?

通常,对于软件断点,调试器会在你设置断点的位置放置一条中断指令。这将程序的控制权转移到调试器的中断处理程序,从那里,调试器可以决定要做什么(向您提供命令提示符、打印堆栈并继续,以及您所做的一切)


在一个相关的注释中,“这在调试器中有效,但在没有断点的情况下运行时不起作用”向我建议您有一个竞争条件。因此,如果你的应用程序是多线程的,考虑检查你的锁定规则。

而不直接回答你的问题(因为我怀疑调试器的内部工作可能不是问题),我会提供两种可能的原因,这是我以前见过的:

首先,您的程序在遇到断点时确实会暂停,而且这种延迟通常足以让某些事情发生(可能是在另一个线程或另一个进程中),而这些事情必须在您的函数工作之前发生。验证这一点的一个简单方法是在程序运行前添加几秒钟的暂停,然后正常运行程序。如果这样做有效,你就必须寻找一种更可靠的方法来发现问题


第二,VisualStudio在调试模式下运行时,历史上(我不确定2008年)分配的内存过多。因此,例如,如果您分配了一个
int[10]
数组,根据权限,它应该获得40个字节的内存,但Visual Studio可能会给它44个或更多,以防出现越界错误。当然,如果您确实有越界错误,这种过度分配可能会使它看起来仍然正常工作。

调试器有时会更改程序的行为方式,以便正常工作

我不确定VisualStudio,但以Eclipse为例。Java类在IDE内部运行和在IDE外部运行时的加载方式不同

您可能还有一个争用条件,调试器会停止其中一个线程,因此当您继续程序流时,它处于正确的条件


有关该程序的更多信息可能会有所帮助。

在Windows上,调试器会导致另一个差异。当调试器启动程序时,Windows将为您的程序使用不同的内存管理器(确切地说是堆管理器)。您的程序现在将获得调试堆管理器,而不是默认堆管理器,这与以下几点不同:

  • 它将分配的内存初始化为一个模式(我想到了0xCDCDCD,但我可能错了)
  • 它用另一个模式填充释放的内存
  • 它过度分配堆分配(如前面提到的答案)
总的来说,它改变了程序的内存使用模式,因此,如果你在某个地方有一个内存崩溃错误,它的行为可能会改变

两个有用的技巧:

  • 使用PageHeap捕获超出已分配块末尾的内存访问
  • 使用/RTCSU(旧的Visual C++编译器:/GX)构建。这会将所有局部变量的内存初始化为非零位模式,并在访问统一化局部变量时引发运行时错误
    比赛条件也是我的第一个想法。这并不是你想要的答案,但我忍不住说:“调试就像放屁一样——当它是你自己的代码时,它并没有那么糟糕。”至少从2008年开始,过度分配的RAM就被用在了金丝雀身上。如果您的代码溢出了一个数组并炸毁了一只金丝雀,那么