C#中项目文件夹 debug 和 release 程序编译执行时的区别
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。 首先说一下C#解决方案下不同文件 Bin 目录用来存放编译的结果,bin是二进制binrary的英文缩写,因为最初C编译的程序文件都是二进制文件,它有Debug和Release两个版本,分别对应的文件夹为bin/Debug和bin/Release,这个文件夹是默认的输出路径,我们可以通过:项目属性—>配置属性—>输出路径来修改。 debug 和releasebin是放最终代码的目录,obj就放中间代码的目录。 release和debug是不同的运行方式 debug会增加调试代码,方便调试。调试完后,用release版本发布,没有调试代码,减小程序体积,加快执行速度! 既然obj就放中间代码的目录,为什吗还要release呢?同理,既然bin是放最终代码的目录还要debug干什吗?不是多此一举吗? 编译一个源程序文件,要经过语法、类型,甚至要判断执行时的可行性等。是一个对文件多次扫描的过程,最后还有代码优化的过程。会有一大堆的中间文件产生。vc6下的一个mfc项目 obj目录里会有好几M的中间(临时)文件。 再复杂点,一个project有图片(声音)等资源文件,要调用其他DLL类库(可能是.net组件,可能是com),还可能由多个.cs文件组成。要把 这么多东西连接在一起。以前在DOS下用C或PASCAL,要先编译成.obj文件,再用link.exe连接在一起,才是一个exe文件。(记得 pascal还是fortran要用两个编译程序才能得到一个.obj的中间文件) debug调试,你在程序中设置了断点,为什么vs.net知道在那里要停下来,当你把鼠标移到某个变量上,vs.net就会显示它当时的值? debug和release区别 一个为调试版本,其中包括了出错时能够定位源代码的在行,如果源文件已经改变,定位出来会有偏移,而且,在这个版本中编译器不会进行代码优化,并且在程序中能用宏定义_DEBUG来确定当前的版本。另一个为正试版本,程序出错只是进行简单的错误处理,编译器会优化代码,以提高性能。 Release代码更小,执行更快,编译更严格,更慢 。当然就没有了调试信息。 遇到DEBUG成功的版本RELEASE 就有问题,以下是问题的分析总结 1. 变量未初始化。下面的程序在debug中运行的很好。 thing * search(thing * something) BOOL found; for(int i = 0; i < whatever.GetSize(); i++) { if(whatever[i]->field == something->field) { found = TRUE; break; } } if(found) return whatever[i]; else return NULL; 而在release中却不行,因为debug中会自动给变量初始化found=FALSE,而在release版中则不会。所以尽可能的给变量、类或结构初始化。 2. 数据溢出的问题,如: char buffer[10]; int counter; lstrcpy(buffer, "abcdefghik"); 在debug版中buffer的NULL覆盖了counter的高位,但是除非counter>16M,什么问题也没有。但是在release版中,counter可能被放在寄存器中,这样NULL就覆盖了buffer下面的空间,可能就是函数的返回地址,这将导致ACCESS ERROR。 3. DEBUG版和RELEASE版的内存分配方式是不同的 。如果你在DEBUG版中申请 ele 为 6*sizeof(DWORD)=24bytes,实际上分配给你的是32bytes(debug版以32bytes为单位分配), 而在release版,分配给你的就是24bytes(release版以8bytes为单位),所以在debug版中如果你写ele[6],可能不会有什么问题,而在release版中,就有ACCESS VIOLATE。
1. ASSERT在Release版本中是不会被编译的。ASSERT宏是这样定义: #ifdef _DEBUG #define ASSERT(x) if( (x) == 0) report_assert_failure() #else #define ASSERT(x) #endif 实际上复杂一些,但无关紧要。假如你在这些语句中加了程序中必须要有的代码,比如: ASSERT(pNewObj = new CMyClass); pNewObj->MyFunction(); 这种时候Release版本中的pNewObj不会分配到空间,所以执行到下一个语句的时候程序会报该程序执行了非法操作的错误。这时可以用VERIFY: #ifdef _DEBUG #define VERIFY(x) if( (x) == 0) report_assert_failure() #else #define VERIFY(x) (x) #endif 这样的话,代码在release版中就可以执行了。 自定义消息的处理函数,必须定义如下: afx_msg LRESULT OnMyMessage(WPARAM, LPARAM); 返回值必须是HRESULT型,否则Debug会过,而Release出错
保证数据创建和清除的统一性:如果一个DLL提供一个能够创建数据的函数,那么这个DLL同时应该提供一个函数销毁这些数据。数据的创建和清除应该在同一个层次上。
人们将不同版本DLL混合造成的不一致性形象的称为 “动态连接库的地狱“(DLL Hell) ,甚至微软自己也这么说(http://msdn.microsoft.com/library/techart/dlldanger1.htm)。 如果你的程序使用你自己的DLL时请注意:
VI. RELEASE板中的调试: 1. 将ASSERT() 改为 VERIFY() 。找出定义在"#ifdef _DEBUG"中的代码,如果在RELEASE版本中需要这些代码请将他们移到定义外。查找TRACE(...)中代码,因为这些代码在RELEASE中也不被编译。 请认真检查那些在RELEASE中需要的代码是否并没有被便宜。
编译器的优化可能导致许多意想不到的错误,请参考http://www.pgh.net/~newcomer/debug_release.htm
该文章在 2024/5/29 9:03:44 编辑过 |
关键字查询
相关文章
正在查询... |