VC实用技巧大全
- 格式:pdf
- 大小:251.66 KB
- 文档页数:28


VC调试技巧之Call StackVC调试技巧之Call Stack简单介绍调试是程序开发者必备技巧。
如果不会调试,自己写的程序一旦出问题,往往无从下手。
本人总结10年使用VC经验,对调试技巧做一个粗浅的介绍。
希望对大家有所帮助。
今天简单的介绍介绍调用堆栈。
调用堆栈在我的专栏的文章VC 调试入门提了一下,但是没有详细介绍。
首先介绍一下什么叫调用堆栈:假设我们有几个函数,分别是function1,function2,function3,funtion4,且function1调用function2,function2调用function3,function3调用function4。
在function4运行过程中,我们可以从线程当前堆栈中了解到调用他的那几个函数分别是谁。
把函数的顺序关系看,function4、function3、function2、function1呈现出一种“堆栈”的特征,最后被调用的函数出现在最上方。
因此称呼这种关系为调用堆栈(call stack)。
当故障发生时,如果程序被中断,我们基本上只可以看到最后出错的函数。
利用call stack,我们可以知道当出错函数被谁调用的时候出错。
这样一层层的看上去,有时可以猜测出错误的原因。
常见的这种中断时ASSERT宏导致的中断。
在程序被中断时,debug工具条的右侧倒数第二个按钮一般是call stack按钮,这个按钮被按下后,你就可以看到当前的调用堆栈。
实例一:介绍我们首先演示一下调用堆栈。
首先我们创建一个名为Debug的对话框工程。
工程创建好以后,双击OK按钮创建消息映射函数,并添加如下代码:?void CDebugDlg::OnOK()?-- TODO: Add extra validation here?ASSERT(FALSE);?我们按F5开始调试程序。
程序运行后,点击OK按钮,程序就会被中断。
这时查看call stack窗口,就会发现内容如下:?CDebugDlg::OnOK() line 176 + 34 bytes_AfxDispatchCmdMsg(CCmdTarget * 0x0012fe74 {CDebugDlg}, unsigned int 1, int 0, void (void)* 0x5f402a00 `vcall'(void), void * 0x00000000, unsigned int 12, AFX_CMDHANDLERINFO * 0x00000000) line 88CCmdTarget::OnCmdMsg(unsigned int 1, int 0, void * 0x00000000, AFX_CMDHANDLERINFO * 0x00000000) line 302 + 39 bytesCDialog::OnCmdMsg(unsigned int 1, int 0, void * 0x00000000, AFX_CMDHANDLERINFO * 0x00000000) line 97 + 24 bytes CWnd::OnCommand(unsigned int 1, long 656988) line 2088CWnd::OnWndMsg(unsigned int 273, unsigned int 1, long 656988, long * 0x0012f83c) line 1597 + 28 bytesCWnd::WindowProc(unsigned int 273, unsigned int 1, long 656988) line 1585 + 30 bytesAfxCallWndProc(CWnd * 0x0012fe74 {CDebugDlg hWnd=?}, HWND__ * 0x001204b0, unsigned int 273, unsigned int 1, long 656988) line 215 + 26 bytesAfxWndProc(HWND__ * 0x001204b0, unsigned int 273, unsigned int 1, long 656988) line 368AfxWndProcBase(HWND__ * 0x001204b0, unsigned int 273, unsigned int 1, long 656988) line 220 + 21 bytesUSER32! 77d48709()USER32! 77d487eb()USER32! 77d4b368()USER32! 77d4b3b4()NTDLL! 7c90eae3()USER32! 77d4b7ab()USER32! 77d7fc9d()USER32! 77d76530()USER32! 77d58386()USER32! 77d5887a()USER32! 77d48709()USER32! 77d487eb()USER32! 77d489a5()USER32! 77d489e8()USER32! 77d6e819()USER32! 77d65ce2()CWnd::IsDialogMessageA(tagMSG * 0x004167d8 {msg=0x00000202 wp=0x00000000 lp=0x000f001c}) line 182 CWnd::PreTranslateInput(tagMSG * 0x004167d8 {msg=0x00000202 wp=0x00000000 lp=0x000f001c}) line 3424 CDialog::PreTranslateMessage(tagMSG * 0x004167d8 {msg=0x00000202 wp=0x00000000 lp=0x000f001c}) line 92 CWnd::WalkPreTranslateTree(HWND__ * 0x001204b0, tagMSG * 0x004167d8 {msg=0x00000202 wp=0x00000000 lp=0x000f001c}) line 2667 + 18 bytesCWinThread::PreTranslateMessage(tagMSG * 0x004167d8 {msg=0x00000202 wp=0x00000000 lp=0x000f001c}) line 665 + 18 bytesCWinThread::PumpMessage() line 841 + 30 bytesCWnd::RunModalLoop(unsigned long 4) line 3478 + 19 bytes CDialog::DoModal() line 536 + 12 bytesCDebugApp::InitInstance() line 59 + 8 bytesAfxWinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ *0x00000000, char * 0x00141f00, int 1) line 39 + 11 bytes WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x00141f00, int 1) line 30WinMainCRTStartup() line 330 + 54 bytesKERNEL32! 7c816d4f()这里,CDebugDialog::OnOK作为整个调用链中最后被调用的函数出现在call stack的最上方,而内核中程序的启动函数Kernel32! 7c816d4f()则作为栈底出现在最下方。
vc6调试技巧难怪很多前辈说调试是⼀个程序员最基本的技能,其重要性甚⾄超过学习⼀门语⾔。
不会调试的程序员就意味着他即使会⼀门语⾔,却不能编制出任何好的软件。
我以前接触的程序⼤多是有⽐较成形的思路和⽅法,调试起来出的问题都⽐较⼩,最近这个是我⾃⼰慢慢摸索调试,接触了很多新的调试⽅法,并查了很多前辈的总结,受益匪浅,总结以前的和新的收获如下:VC调试篇设置为了调试⼀个程序,⾸先必须使程序中包含调试信息。
⼀般情况下,⼀个从AppWizard创建的⼯程中包含的Debug Configuration⾃动包含调试信息,但是是不是Debug版本并不是程序包含调试信息的决定因素,程序设计者可以在任意的Configuration中增加调试信息,包括Release版本。
为了增加调试信息,可以按照下述步骤进⾏:打开Project settings对话框(可以通过快捷键ALT+F7打开,也可以通过IDE菜单Project/Settings打开)选择C/C++页,Category中选择general ,则出现⼀个Debug Info下拉列表框,可供选择的调试信息⽅式包括:选择Link页,选中复选框"Generate Debug Info",这个选项将使连接器把调试信息写进可执⾏⽂件和DLL如果C/C++页中设置了Program Database以上的选项,则Link incrementally可以选择。
选中这个选项,将使程序可以在上⼀次编译的基础上被编译(即增量编译),⽽不必每次都从头开始编译。
调试⽅法:1、使⽤ Assert(原则:尽量简单)assert只在debug下⽣效,release下不会被编译。
2、防御性的编程3、使⽤Trace4、⽤GetLastError来检测返回值,通过得到错误代码来分析错误原因5、把错误信息记录到⽂件中位置断点(Location Breakpoint)⼤家最常⽤的断点是普通的位置断点,在源程序的某⼀⾏按F9就设置了⼀个位置断点。
CCVC 自然拼读CCVC 自然拼读是一种帮助儿童学习发音和阅读的教学方法,通过将辅音和元音组合在一起,形成有意义的单词,帮助孩子们更好地理解英语音标和发音规则。
在这篇文章中,我们将介绍 CCVC 自然拼读的原理和教学方法,并分享一些有效的教学技巧。
什么是 CCVC 自然拼读CCVC 即辅音-辅音-元音-辅音,是英语中的一种音节结构。
CCVC 自然拼读是通过将这些元音和辅音组合在一起,形成有意义的单词,以帮助儿童更好地理解和掌握英语的发音规则。
这种教学方法可以帮助孩子们通过简单的拆分和组合,轻松地识别和阅读单词。
CCVC 自然拼读的原理CCVC 自然拼读的原理基于英语单词的音节结构和发音规则。
在 CCVC 自然拼读中,每个辅音和元音组合都有自己的发音规则,这些规则可以帮助儿童更好地发音和理解单词的意思。
在 CCVC 自然拼读中,首先教授儿童每个字母的发音,并让他们熟悉一些常见的辅音和元音组合。
然后,通过将这些辅音和元音组合在一起,构建出有意义的单词,帮助孩子们理解和记忆这些发音规则。
CCVC 自然拼读的教学方法1.分步教学: CCVC 自然拼读的教学过程应该分为多个步骤。
首先,教授每个字母和它的发音。
然后,教授一些常见的辅音和元音组合,并引导孩子们发音。
最后,通过将这些组合在一起,教授孩子们识别和阅读一些有意义的CCVC 单词。
2.互动练习:在教授 CCVC 自然拼读时,可以使用互动的练习方法。
例如,教师可以提供一个单词的字母拆分,让学生组合出正确的单词。
这样的练习可以帮助孩子们巩固所学的发音规则,并提高他们的阅读能力。
3.游戏和活动:利用游戏和活动可以增加教学的趣味性和参与度。
例如,可以打印一些 CCVC 单词的卡片,让学生参与卡片配对游戏。
这样的游戏不仅可以帮助孩子们复习发音规则,还可以提高他们的注意力和记忆力。
4.综合应用:在教学 CCVC 自然拼读时,要搭配综合应用的练习。
例如,让学生用所学的CCVC 单词写句子或段落,以提高他们的写作和语言表达能力。
VC编程实现软件多语言功能在软件开发的过程中,很多时候需要实现多语言的功能,以满足不同用户的语言需求。
在VC编程中,可以通过一些技巧和方法来实现软件的多语言功能。
首先,VC编程中可以使用资源文件来实现多语言的功能。
资源文件通常以.rc为扩展名,可以包含程序中用到的所有文本、图像等资源。
在资源文件中,可以为每个资源定义不同语言的版本。
通过在资源文件中定义多个语言的资源,程序在运行时会根据用户的语言设置来自动加载对应的资源。
这样,用户使用不同语言的操作系统或设置不同的语言首选项都能够显示对应的语言界面。
其次,VC编程中可以利用GetSystemDefaultLCID函数来获取操作系统的默认语言区域代码。
根据语言区域代码的不同,可以加载对应的语言资源。
通过这种方式,可以使程序自动适应用户的语言设置,无需用户手动选择语言。
另外,VC编程中可以使用其他第三方库或框架来实现多语言功能。
例如,可以使用Qt框架的国际化(Internationalization,i18n)功能来轻松实现多语言功能。
Qt提供了一个称为Qt Linguist的工具,可以用于翻译程序界面的文本。
通过使用Qt Linguist,可以将程序的文本提取到一个单独的翻译文件中,然后根据语言设置加载相应的翻译文件,实现多语言的功能。
此外,为了方便用户切换语言,可以在程序的设置或首选项中提供一个选项,用户可以自行选择使用的语言。
通过保存用户选择的语言设置,下次运行程序时自动加载对应的语言资源。
总结起来,VC编程实现软件多语言功能的关键在于正确地加载和显示对应的语言资源。
通过使用资源文件、操作系统默认语言和第三方库等方式,可以实现软件多语言功能,提供更好的用户体验。