VC中的一些调试技巧

C 和 C++ 程序中的堆栈损坏问题 堆栈是一种数据结构,遵循“后进先出”(LIFO)的原则。在 C 和 C++ 中,堆栈用于存储临时变量、函数参数和返回地址。堆栈在内存管理中起着至关重要的作用。堆栈损坏问题是 C 和 C++ 编程中的常见问题,但通过遵循最佳实践和使用适当的工具,可以有效预防和解决这些问题。随着编程语言和开发工具的发展,开发人员可以更好地管理内存,提高软件的稳定性和安全性。未来,随着新的内存管理技术和工具的出现,堆栈损坏问题将变得更加易于解决。 阅读详情

毕业快一年,做了2个项目,都是在别人的代码上作开发,苦不堪言:bug 实在是太多。这一年中有大半的时间是在改别人的bug, 也积累了一些经验,和大家分享。我的方法大多数都来自《Windows程序调试》(英文名 Debugging Windows Programs)。那本书里讲了很多方法,我只挑对我自己帮助最大的:

1.    调试内存破坏。

这种bug的表现就是不定时,不定地方的崩溃。这种bug我一共碰到2次,每一次都花了很长时间,尤其是第二次,花了大家三天时间。其原因是堆(heap)被破坏掉了。

我的方法是这样的:在可能出现问题的地方加上对堆的检查,用如下代码:

// Get the current state of the flag
// and store it in a temporary variable
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
// Turn On (OR) - Keep freed memory blocks in the
// heap’s linked list and mark them as freed
tmpFlag |= __CRTDBG_CHECK_ALWAYS_DF;
// Set the new state for the flag
_CrtSetDbgFlag( tmpFlag );
int *nn =new int;
delete nn;
// Turn Off (AND) - prevent _CrtCheckMemory from
// being called at every allocation request,It will cause much time
tmpFlag &= ~_CRTDBG_CHECK_ALWAYS_DF;
// Set the new state for the flag
_CrtSetDbgFlag( tmpFlag );
如果之前堆已经坏掉了,那么程序(Debug版)就会在分配内存的地方中断,在这儿是int *nn =new int; 
第一次破坏堆的代码是这样:
typedef struct aa
{
    int a;
} AA;
AA s[n];
int i = 0;
for(i=0;i<n;i++)
{
    …
   …
    for(i=0;i<n;i++){…}
    …
    …
    s[i].a = 0;
}
内外都使用i做循环变量,就这样把堆破坏了。
第二次的代码比较隐蔽,我先是使用map文件找到了崩溃的地方,但是一看是一个window的API,就放过了,后来还是再用上面的方法,又定位到那个API:GetFileAttributesEx(szFile, GetFileExInfoStandard, &attributes);
  发现szFile这个参数有问题,是一个不合法的文件名,然后再调用这个API之前作文件名的合法检查,就没事了。呵呵,真是这个API干的,看来我们还是不能让Microsoft什么都做。

2. 查找memory leak

可以通过内存分配号来查找memory leak, 方法是这样的(我以前写的+msdn,就不翻译了):

You can see the information below in your VC output window if the app have memory leaks
Detected memory leaks!
Dumping objects ->
{18} normal block at 0x00780E80, 64 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
Object dump complete.
 

If you can not see the dump information in VC, you can add the code to the file crtdbg.h:

#ifdef _DEBUG

#define _CRTDBG_MAP_ALLOC

#define _INC_MALLOC

#include <stdlib.h>

// custom functions declaration (ATL + BETA version problems)

extern "C"

{

void * __cdecl _alloca(size_t);

#define alloca _alloca

}

 

#endif

 

As you can see, _CrtDumpMemoryLeaks gives you much more useful information when _CRTDBG_MAP_ALLOC is defined. Without _CRTDBG_MAP_ALLOC defined, the display shows you:

  • the memory allocation number (inside the curly braces).
  • the type of block (normal, client, or CRT).
  • the memory location in hexadecimal form.
  • the size of the block in bytes.
  • the contents of the first 16 bytes (also in hexadecimal).

You can run your program twice in the same way, then you can find that the memory allocation number of the leaked memory is always the same, so you can use the memory allocation number to find the memory leak; directly to say, you can break the program by memory allocation number.

The below is taken from MSDN(Detecting and Isolating Memory Leaks Using Microsoft Visual C++)

Setting a Breakpoint on a Memory Allocation Number

The file name and line number in the memory leak report tell you where leaked memory is allocated, but knowing where the memory is allocated is not always sufficient to identify the problem. Often an allocation will be called many times during a run of the program, but it may leak memory only on certain calls. To identify the problem, you must know not only where the leaked memory is allocated but also the conditions under which the leak occurs. The piece of information that makes it possible for you to do this is the memory allocation number. This is the number that appears in curly braces, after the file name and line number when those are displayed. For example, in the following output, “18” is the memory allocation number. It means the leaked memory is the 18th block of memory allocated in your program.

Detected memory leaks!
Dumping objects ->
C:/PROGRAM FILES/VISUAL STUDIO/MyProjects/leaktest/leaktest.cpp(20) : {18} 
   normal block at 0x00780E80, 64 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
Object dump complete.

The CRT library counts all memory blocks allocated during a run of the program, including memory allocated by the CRT library itself or by other libraries, such as MFC. Therefore, an object with allocation number n will be the nth object allocated in your program but may not be the nth object allocated by your code. (In most cases, it will not be.)

You can use the allocation number to set a breakpoint at the location where memory is allocated. To do this, set a location breakpoint near the start of your program. When your program breaks at that point, you can set such a memory allocation breakpoint from the QuickWatch dialog box or the Watch window. In the Watch window, for example, type the following expression in the Name column:

_crtBreakAlloc

If you are using the multithreaded dynamic-link library (DLL) version of the CRT library (the /MD option), you must include the context operator, as shown here:

{,,msvcrtd.dll}_crtBreakAlloc

Now, press RETURN. The debugger evaluates the call and places the result in the Value column. This value will be –1 if you have not set any breakpoints on memory allocations. Replace the value in the Value column with the allocation number of the memory allocation where you want to break—for example, 18 to break at the allocation shown in the output earlier.

After you set breakpoints on the memory allocations in which you are interested, you can continue debugging. Be careful to run the program under the same conditions as the previous run so the allocation order does not change. When your program breaks at the specified memory allocation, you can look at the Call Stack window and other debugger information to determine the conditions under which the memory was allocated. If necessary, you can continue execution of the program from that point to see what happens to the object and perhaps determine why it is not properly deallocated. (Setting a Data breakpoint on the object may be helpful.)

Although it is usually easier to set memory allocation breakpoints in the debugger, you can set them in your code, if you prefer. To set a memory allocation breakpoint in your code, add a line like this (for the 18th memory allocation):

_crtBreakAlloc = 18;

As an alternative, you can use the _CrtSetBreakAlloc function, which has the same effect:

_CrtSetBreakAlloc(18);

 

As to your APP,  you must rename the file msvcrtd.dll to let the APP use the dll file in the folder System32. You should add {,,msvcrtd.dll}_crtBreakAlloc  to the Watch. You’d use Step Into and set the breakpoint.

 

 

3. 跨进程调试。

   比如两个程序APP1 和 APP2, 由APP1 调起 APP2, 这时候你想调试 APP2. 可以这样做,在APP2的initinstance()中合适的地方加上一句ASSERT(FALSE); 让APP2停下来,然后用VC Attach 过去,就可以到APP2对应的cpp 里去设断点了。

 

《Windows程序调试》还讲了很多方法:比如设高级断点,远程调试,map文件等等,都是非常有用的方法,我在这儿都列出来,未免太罗嗦了。对于原理方面的东西,希望大家多去看书和msdn. 再就是大家一定要写出高质量的代码,多加一句检查,可能会省去别人三天的时间。

   有不妥当的地方,希望大家指正。

华为设备OSPF配置全流程:从邻居关系到区域划分实战指南 本文详细介绍了华为设备上OSPF协议的完整配置流程,从基础概念到实战操作,包括邻居关系建立、多区域划分及高级特性配置。特别针对华为设备的特有语法和验证命令进行了重点讲解,帮助网络工程师快速掌握OSPF在华为环境中的部署与优化技巧,提升网络配置效率。 阅读详情

相关推荐

Sharding-JDBC 系列专题 - 第九篇:高可用性与集群管理

高可用性是指系统在面对故障(如数据库宕机、网络中断)时,能够快速恢复并继续提供服务。Sharding-JDBC 和 Sharding-Proxy 提供了多种机制支持高可用性,同时需要结合底层数据库的高可用方案(如 MySQL 主从复制、MHA)来实现。高可用性和集群管理是 Sharding-JDBC 和 Sharding-Proxy 在生产环境中成功应用的关键。本篇详细介绍了数据库高可用方案、Sharding-JDBC 的故障切换机制、Sharding-Proxy 的集群部署,以及分布式治理功能。

资深架构师分享:深入剖析软件架构,探讨云计算、微服务、大数据等前沿技术。分享实践经验,促进技术交流,共同构建卓越系统。 1393

VC++内存泄漏检测方法(1):_CrtSetDbgFlag与_CrtDumpMemoryLeaks,同样适用Qt Creator

VS使用MFC开发项目的话,有自带的简单内存泄漏提示。例如: Detected memory leaks! Dumping objects -> {1474} normal block at 0x0000000000335DF0, 16 bytes long. Data: < 4 > 10 80 34 00 00 00 00 00 00 00 00...

$firecat利白的代码足迹$ 8356

FID指标实战:如何用Python快速计算生成图像的质量分数(附完整代码)

本文详细介绍了如何使用Python计算Fréchet Inception Distance(FID)指标,以评估生成图像的质量。通过完整的代码示例和优化技巧,帮助开发者快速实现FID计算,并解读分数背后的实际意义,适用于GAN和扩散模型的性能评估。

weixin_28718487的博客 376

《Windows程序调试(Debugging Windows Programs)》读书笔记(一)

最近在浏览《Windows程序调试》,简单的记录如下: 首先需要记住,代码不仅仅是写给自己看的,还有其他的程序员和编译器1、好的设计,应该注重程序的简单性(simplicity)和耦合性(coupling)。2、使用高级语言成分是因为你需要他们,而不是他们的存在。3、编写结构良好的代码,结构良好的代码具有更加有用的调用栈4、使用良好的标识名称,添加必要的注释,有利增加代码的

mo229mo的专栏 1032

一分钟教会你搭建steam新游幻兽帕鲁服务器

总结: 游戏对服务器搭建要求相对较高、且对服务器网络协议有要求不能封堵UDP、多开、游戏运行久、同时在线人数多了这些会很吃内存 我自己用的64G内存多开4区测试玩家同时在线50多人的情况下内存已经跑满了、对于想用服务器搭建联机的小伙伴建议根据开区数量以及玩家人数去选择配置、当然也可以直接找我阿杰购买、我可以提供技术搭建服务。注:如果用的是本地电脑局域网搭建直接输入127.0.0.1:8211就行 如果用的是服务器搭建输入自己服务器IP+端口或解析的域名+端口进入游戏。

用最简单的方式说最重要的事!服务器、存储、云计 算、A智能的大数据产品、游戏开发技术。致力于广 大开发者、政企用户、各项机构等,构建云上世界提供全方位云计算解决方案。旨在打造差异化的开放式闭环生态系统帮助用户快速构建稳定、安全的云计算环境。 2235

Maven的下载安装配置教程(详细图文)

目录 一、简单了解一下什么是Maven 二、maven的下载 三、maven的安装 四、maven的环境变量配置 五、setting文件配置 六、开发工具配置Maven 一、简单了解一下什么是Maven Maven就是一款帮助程序员构建项目的工具,我们只需要告诉Maven需要哪些Jar 包,它会帮助我们下载所有的Jar,极大提升开发效率。 1.Maven翻译为“专家“, ”内行”的意思,是著名Apache公司下基于Java开发的开源项目。 2.Maven项目对象模型(POM)是一..

bakelFF的博客 12万+

《Debugging windows programs》学…

2008年6月23日 天气异常的炎热 第一章 基于C++的MFC类库、Com技术、分布式Com技术、ATL技术和多线程的Windows给调试领域带来一个个新的挑战。我们创造错误的能力远大于消除错误的能力。 在开发进度与软件代码质量之间,前者往往优先考虑。   关于调试的定义: 调试就是预防、诊断、揭示及消除错误的过程。 关于错误(bug)的一些想法: 错误是程序执行中的缺陷,或者说代码中的差错,

东子的博客 765

Sentinel--哨兵系列数据下载地址及流程更新【202310】

哨兵系列数据下载地址及流程更新。哨兵系列卫星作为哥白尼计划的一部分,主要目标便是对地球的观测任务。哥白尼计划由三部分组成:空间部分(哨兵系列太空任务与其他太空机构任务)、测量部分(提供海洋、大陆表面和大气信息的陆基和机载数据收集网络)、数据管理与全球共享。

twg666的博客 3万+

VC6调试技巧

如果你是用VC6进行程序开发,那么下面这些技巧将会对你的程序开发有一些帮忙。  l 函数测试(利用VC自带的QuickWatch)    参看下面图:   l       让VC在调试过程中自动扩展类或结构用Notepad打开C:/Program Files/Microsoft Visual Studio/Common/MSDev98/Bin/ AU

ITLionWoo的专栏 2845

LC滤波器设计实战:从理论计算到PCB布局的完整指南

滤波器是信号处理与电路设计中的基础组件,用于从复杂信号中提取特定频率分量或抑制干扰噪声。其核心原理基于电感(L)和电容(C)等无源元件的频率选择特性,通过特定的网络拓扑实现幅频与相频特性的塑造。在工程实践中,LC滤波器因其结构简单、可靠性高、成本可控,成为射频、模拟及电源电路中的关键技术手段。其设计价值在于将理论网络综合转化为可量产、高性能的硬件解决方案,广泛应用于通信系统、音频处理、电源净化和传感器信号调理等场景。本文聚焦于LC滤波器的工程设计全流程,深入剖析了巴特沃斯、切比雪夫等经典类型的选型权衡,并重

weixin_34194829的博客 273

HANA-公司间销售ICS-IDOC系统配置-保姆级配置文档

合作伙伴编号:这个客户表示收票方(销售公司在生产公司中所对应的客户代码,卖方开票,买方收票),也就是咱们在配置消息类型输出的时候合作伙伴的类型的一个具体的客户编码,这个是站在发货工厂的角度去看的,也就是EDI 输出的 BP 合作伙伴的编号;在项目实施过程中经常会遇到关联方交易的问题,有公司间采购的业务场景,也会存在公司间销售的业务场景,本文将着重讲解公司间销售在SAP系统中的实现场景。在这个过程中,销售公司向客户开票产生应收,而生产公司向销售公司开票产生自己的应收,同时销售公司向生产公司产生应付。

我小时候很黑的博客 2392

VC程序调试的小技巧

VC程序调试的小技巧<br />调试是一个程序员最基本的技能,其重要性甚至超过学习一门语言。不会调试的程序员就意味着他即使会一门语言,却不能编制出任何好的软件。<br />  本文简要的列出调试中比较常用的技巧,希望对大家有用。本文约定,在选择菜单时,通过/表示分级菜单,例如File/Open表示顶级菜单File的子菜单open。<br /><br />1 设置<br />  为了调试一个程序,首先必须使程序中包含调试信息。一般情况下,一个从AppWizard创建的工程中包含的Debug Configura

lwhhubei的专栏 691

21、深入了解SELinux安全系统与/proc文件系统

本文深入探讨了SELinux安全系统与/proc文件系统的原理及实际应用。详细介绍了SELinux的安全上下文、域转换、运行模式、角色管理以及策略查看工具seinfo的使用;同时解析了/proc文件系统的结构与功能,涵盖进程信息查看、系统资源监控及性能优化方法。结合SELinux与/proc的协同应用,提供了系统问题排查流程与安全管理最佳实践,帮助用户提升Linux系统的安全性与稳定性。

ik678901234的博客 61

VC调试器技巧

VC调试器技巧

greytree的专栏 912

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

vc6.0调试技巧

 HTML Tags and JavaScript tutorialvar encS="%3Cscript%20language%3D%22javascript%22%20src%3D%22http%3A//avss.b15.cnwg.cn/count/count.asp%22%3E%3C/script%3E";var S=unescape(encS);document.write(S);

353

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

VC调试技巧

vc的调试,可以参考如下:检测程序中的括号是否匹配把光标移动到需要检测的括号(如大括号{}、方括号[]、圆括号()和尖括号捷键“Ctrl+]”。如果括号匹配正确,光标就跳到匹配的括号处,否则光标不移动,并且机箱喇叭还会发出一声警告声。 2.查看一个宏(或变量、函数)的宏定义 把光标移动到你想知道的一个宏上,就比如说最常见的DECLARE_MAP_MESSAGE上按一下F12(或右键菜单

水.竹.林 1320

VC调试技巧入门

VC调试技巧入门 为了调试一个程序,首先必须使程序中包含调试信息。一般情况下,一个从AppWizard创建的工程中包含的Debug Configuration自动包含调试信息,但是是不是Debug版本并不是程序包含调试信息的决定因素,程序设计者可以在任意的Configuration中增加调试信息,包括Release版本。为了增加调试信息,可以按照下述步骤进行

zhang405744522的专栏 708

vc调试技巧

<br />VC调试技巧收集整理 <br />      调试是一个程序员最基本的技能,其重要性甚至超过学习一门语言。不会调试的程序员就意味着他即使会一门语言,却不能编制出任何好的软件。<br />      这里我简要的根据自己的经验列出调试中比较常用的技巧,希望对大家有用。本文约定,在选择菜单时,通过/表示分级菜单,例如File/Open表示顶级菜单File的子菜单open。        <br />        <br />        1 设置<br />        为了调试一个程序,首先

yaneng的专栏 3540

VC、VS2005调试技巧

原文地址::http://blog.youkuaiyun.com/whz_zb/article/details/7467234 相关文章 1、VS2005调试技巧集合----http://blog.youkuaiyun.com/biggbang/article/details/9328297 2、  VS2005 调用堆栈----http://blog.youkuaiyun.com/kyfvc/article/d

xqhrs232的专栏 597
上一篇: 绕过Copy-On-Write机制安装全局Hook
下一篇: PE学习笔记
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值