1.release��Դ��
2.Release 版本的源码程序与Debug版本的程序有什么不同?以常见的开发环境举例说明
3.项目发布Debug和Release版的区别
4.c#debug和release的区别
5.releaseådebugçåºå«
release��Դ��
在深入理解Java并发编程时,必不可少的源码是对Semaphore源码的剖析。本文将带你探索这一核心组件,源码通过实践和源码解析,源码掌握其限流和共享锁的源码本质。Semaphore,源码图片ppt网站源码中文名信号量,源码就像一个令牌桶,源码任务执行前需要获取令牌,源码处理完毕后归还,源码确保资源访问的源码有序进行。
首先,源码Semaphore主要有acquire()和release()两个方法。源码acquire()负责获取许可,源码若许可不足,源码任务会被阻塞,直到有许可可用。release()用于释放并归还许可,确保资源释放后,其他任务可以继续执行。一个典型的例子是,如果一个线程池接受个任务,但Semaphore限制为3,那么任务将按每3个一组执行,确保系统稳定性。
Semaphore的源码实现巧妙地结合了AQS(AbstractQueuedSynchronizer)框架,通过Sync同步变量管理许可数量,公平锁和非公平锁的实现方式有所不同。公平锁会优先处理队列中的任务,而非公平锁则按照获取许可的顺序进行。
acquire()方法主要调用AQS中的acquireSharedInterruptibly(),并进一步通过tryReleaseShared()进行许可更新,公平锁与非公平锁的区别在于判断队列中是否有前置节点。release()方法则调用releaseShared(),更新许可数量。最好的黄金分割指标源码
Semaphore的简洁逻辑在于,AQS框架负责大部分并发控制,子类只需实现tryReleaseShared()和tryAcquireShared(),专注于许可数量的管理。欲了解AQS的详细流程,可参考之前的文章。
最后,了解了Semaphore后,我们还将继续探索共享锁CyclicBarrier的实现,敬请期待下篇文章。
Release 版本的程序与Debug版本的程序有什么不同?以常见的开发环境举例说明
(以VC为例)Debug通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。
Debug 和 Release 的真正秘密,在于一组编译选项。下面列出了分别针对二者的选项(当然除此之外还有其他一些,如/Fd /Fo,但区别并不重要,通常他们也不会引起 Release 版错误,在此不讨论)
Debug 版本
参数 含义
/MDd /MLd 或 /MTd 使用 Debug runtime library (调试版本的运行时刻函数库)
/Od 关闭优化开关
/D "_DEBUG" 相当于 #define _DEBUG,打开编译调试代码开关 (主要针对assert函数)
/ZI 创建 Edit and continue(编辑继续)数据库,这样在调试过程中如果修改了源代码不需重新编译
/GZ 可以帮助捕获内存错误
/Gm 打开最小化重链接开关, 减少链接时间
Release 版本
参数 含义
/MD /ML 或 /MT 使用发布版本的运行时刻函数库
/O1 或 /O2 优化开关,使程序最小或最快
/D "NDEBUG" 关闭条件编译调试代码开关 (即不编译assert函数)
/GF 合并重复的字符串, 并将字符串常量放到只读内存, 防止被修改
实际上,Debug 和 Release 并没有本质的界限,他们只是一组编译选项的集合,编译器只是按照预定的选项行动。事实上,h5在线制作网站源码我们甚至可以修改这些选项,从而得到优化过的调试版本或是带跟踪语句的发布版本。
哪些情况下 Release 版会出错
有了上面的介绍,我们再来逐个对照这些选项看看 Release 版错误是怎样产生的
1、Runtime Library:链接哪种运行时刻函数库通常只对程序的性能产生影响。调试版本的 Runtime Library 包含了调试信息,并采用了一些保护机制以帮助发现错误,因此性能不如发布版本。编译器提供的 Runtime Library 通常很稳定,不会造成 Release 版错误;倒是由于 Debug 的 Runtime Library 加强了对错误的检测,如堆内存分配,有时会出现 Debug 有错但 Release 正常的现象。应当指出的是,如果 Debug 有错,即使 Release 正常,程序肯定是有 Bug 的,只不过可能是 Release 版的某次运行没有表现出来而已。
2、优化:这是造成错误的主要原因,因为关闭优化时源程序基本上是直接翻译的,而打开优化后编译器会作出一系列假设。这类错误主要有以下几种:
1. 帧指针(Frame Pointer)省略(简称FPO):在函数调用过程中,所有调用信息(返回地址、参数)以及自动变量都是放在栈中的。若函数的声明与实现不同(参数、返回值、调用方式),就会产生错误,但 Debug 方式下,栈的访问通过 EBP 寄存器保存的地址实现,如果没有发生数组越界之类的错误(或是越界“不多”),函数通常能正常执行;Release 方式下,优化会省略 EBP 栈基址指针,这样通过一个全局指针访问栈就会造成返回地址错误是通达信平台画线源码程序崩溃。
C++ 的强类型特性能检查出大多数这样的错误,但如果用了强制类型转换,就不行了。你可以在 Release 版本中强制加入/Oy-编译选项来关掉帧指针省略,以确定是否此类错误。此类错误通常有:MFC 消息响应函数书写错误。正确的应为:
afx_msg LRESULT OnMessageOwn
(WPARAM wparam, LPARAM lparam);
ON_MESSAGE 宏包含强制类型转换。防止这种错误的方法之一是重定义 ON_MESSAGE 宏,把下列代码加到 stdafx.h 中(在#include "afxwin.h"之后),函数原形错误时编译会报错。
#undef ON_MESSAGE
#define ON_MESSAGE(message, memberFxn) /
{
message, 0, 0, 0, AfxSig_lwl, /
(AFX_PMSG)(AFX_PMSGW)
(static_cast< LRESULT (AFX_MSG_CALL /
CWnd::*)(WPARAM, LPARAM) > (&memberFxn)
},
2. volatile 型变量:volatile 告诉编译器该变量可能被程序之外的未知方式修改(如系统、其他进程和线程)。优化程序为了使程序性能提高,常把一些变量放在寄存器中(类似于 register 关键字),而其他进程只能对该变量所在的内存进行修改,而寄存器中的值没变。
如果你的程序是多线程的,或者你发现某个变量的值与预期的不符而你确信已正确的设置了,则很可能遇到这样的问题。这种错误有时会表现为程序在最快优化出错而最小优化正常。把你认为可疑的变量加上 volatile 试试。
3. 变量优化:优化程序会根据变量的使用情况优化变量。例如,函数中有一个未被使用的变量,在 Debug 版中它有可能掩盖一个数组越界,而在 Release 版中,这个变量很可能被优化调,此时数组越界会破坏栈中有用的数据。当然,实际的情况会比这复杂得多。与此有关的错误有非法访问,包括数组越界、指针错误等。例如:
void fn(void)
{
int i;
i = 1;
int a[4];
{
int j;
j = 1;
}
a[-1] = 1;
//当然错误不会这么明显,例如下标是海龟交易量化案例源码图变量
a[4] = 1;
}
j 虽然在数组越界时已出了作用域,但其空间并未收回,因而 i 和 j 就会掩盖越界。而 Release 版由于 i、j 并未其很大作用可能会被优化掉,从而使栈被破坏。
3. DEBUG 与 NDEBUG :当定义了 _DEBUG 时,assert() 函数会被编译,而 NDEBUG 时不被编译。此外,TRACE() 宏的编译也受 _DEBUG 控制。
所有这些断言都只在 Debug版中才被编译,而在 Release 版中被忽略。唯一的例外是 VERIFY()。事实上,这些宏都是调用了assert()函数,只不过附加了一些与库有关的调试代码。如果你在这些宏中加入了任何程序代码,而不只是布尔表达式(例如赋值、能改变变量值的函数调用等),那么Release版都不会执行这些操作,从而造成错误。初学者很容易犯这类错误,查找的方法也很简单,因为这些宏都已在上面列出,只要利用 VC++ 的 Find in Files 功能在工程所有文件中找到用这些宏的地方再一一检查即可。另外,有些高手可能还会加入 #ifdef _DEBUG 之类的条件编译,也要注意一下。
顺便值得一提的是VERIFY()宏,这个宏允许你将程序代码放在布尔表达式里。这个宏通常用来检查 Windows API的返回值。有些人可能为这个原因而滥用VERIFY(),事实上这是危险的,因为VERIFY()违反了断言的思想,不能使程序代码和调试代码完全分离,最终可能会带来很多麻烦。因此,专家们建议尽量少用这个宏。
4. /GZ 选项:这个选项会做以下这些事:
1. 初始化内存和变量。包括用 0xCC 初始化所有自动变量,0xCD ( Cleared Data ) 初始化堆中分配的内存(即动态分配的内存,例如 new ),0xDD ( Dead Data ) 填充已被释放的堆内存(例如 delete ),0xFD( deFencde Data ) 初始化受保护的内存(debug 版在动态分配内存的前后加入保护内存以防止越界访问),其中括号中的词是微软建议的助记词。这样做的好处是这些值都很大,作为指针是不可能的(而且 位系统中指针很少是奇数值,在有些系统中奇数的指针会产生运行时错误),作为数值也很少遇到,而且这些值也很容易辨认,因此这很有利于在 Debug 版中发现 Release 版才会遇到的错误。要特别注意的是,很多人认为编译器会用0来初始化变量,这是错误的(而且这样很不利于查找错误)。
2. 通过函数指针调用函数时,会通过检查栈指针验证函数调用的匹配性。(防止原形不匹配)
3. 函数返回前检查栈指针,确认未被修改。(防止越界访问和原形不匹配,与第二项合在一起可大致模拟帧指针省略 FPO )通常 /GZ 选项会造成 Debug 版出错而 Release 版正常的现象,因为 Release 版中未初始化的变量是随机的,这有可能使指针指向一个有效地址而掩盖了非法访问。除此之外,/Gm/GF等选项造成错误的情况比较少,而且他们的效果显而易见,比较容易发现。
怎样“调试” Release 版的程序
遇到Debug成功但Release失败,显然是一件很沮丧的事,而且往往无从下手。如果你看了以上的分析,结合错误的具体表现,很快找出了错误,固然很好。但如果一时找不出,以下给出了一些在这种情况下的策略。
1. 前面已经提过,Debug和Release只是一组编译选项的差别,实际上并没有什么定义能区分二者。我们可以修改Release版的编译选项来缩小错误范围。如上所述,可以把Release 的选项逐个改为与之相对的Debug选项,如/MD改为/MDd、/O1改为/Od,或运行时间优化改为程序大小优化。注意,一次只改一个选项,看改哪个选项时错误消失,再对应该选项相关的错误,针对性地查找。这些选项在Project/Settings...中都可以直接通过列表选取,通常不要手动修改。由于以上的分析已相当全面,这个方法是最有效的。
2. 在编程过程中就要时常注意测试 Release 版本,以免最后代码太多,时间又很紧。
3. 在 Debug 版中使用 /W4 警告级别,这样可以从编译器获得最大限度的错误信息,比如 if( i =0 )就会引起 /W4 警告。不要忽略这些警告,通常这是你程序中的 Bug 引起的。但有时 /W4 会带来很多冗余信息,如 未使用的函数参数 警告,而很多消息处理函数都会忽略某些参数。我们可以用:
#progma warning(disable: )
//禁止
//...
#progma warning(default: )
//重新允许来暂时禁止某个警告,或使用
#progma warning(push, 3)
//设置警告级别为 /W3
//...
#progma warning(pop)
//重设为 /W4
来暂时改变警告级别,有时你可以只在认为可疑的那一部分代码使用 /W4。
4. 你也可以像Debug一样调试你的Release版,只要加入调试符号。在Project/Settings... 中,选中 Settings for "Win Release",选中 C/C++ 标签,Category 选 General,Debug Info 选 Program Database。再在 Link 标签 Project options 最后加上 "/OPT:REF" (引号不要输)。这样调试器就能使用 pdb 文件中的调试符号。
但调试时你会发现断点很难设置,变量也很难找到?这些都被优化过了。不过令人庆幸的是,Call Stack窗口仍然工作正常,即使帧指针被优化,栈信息(特别是返回地址)仍然能找到。这对定位错误很有帮助。
项目发布Debug和Release版的区别
项目开发中的Debug与Release版本有着显著的区别:
Debug版本,即调试版,主要用于开发阶段。它包含详尽的调试信息,如断点和源代码映射,这使得程序员能够轻松地追踪和修复错误。不过,由于这些额外信息的存在,Debug版本的文件通常比Release版本大很多,且未进行性能优化。在Debug模式下,编译结果会生成.exe或.dll文件以及.pdb调试文件。
相比之下,Release版本是为最终用户设计的。它去除了调试信息,通过优化代码来提高运行速度和减小文件大小,以提供最优的用户体验。在Release模式下,编译结果仅包含一个.exe或.dll文件,而调试信息通常会单独存储在PDB文件中。
obj目录在项目中扮演着重要角色,它根据Debug或Release模式分别保存编译过程中的临时文件和模块编译结果,通过增量编译加快构建速度。Debug和Release版本的区别主要体现在编译选项上,如开启或关闭优化、调试代码编译等。
在实际应用中,应尽量避免Debug和Release版本的DLL混淆使用,因为这可能导致兼容性问题,即“DLL地狱”。解决方案是根据项目状态,将Debug版与Release版分别放置在对应的目录下,确保生产环境中使用的是优化过的Release版本。
总的来说,Debug和Release版本的选择取决于项目的阶段和需求,Release版本在生产环境中通常更为理想,因为它提供了最小化的文件大小和高效的运行性能。
c#debug和release的区别
debug版本包括调试信息,所以要比release版本大很多(可能大数百k至数m)。至于是否需要dll支持,主要看你采用的编译选项。如果是基于atl的,则debug和release版本对dll的要求差不多。如果采用的编译选项为使用mfc动态库,则需要mfcd.dll等库支持,而release版本需要mfc.dll支持。release
build不对源代码进行调试,不考虑mfc的诊断宏,使用的是mfc
release库,编译十对应用程序的速度进行优化,而debug
build则正好相反,它允许对源代码进行调试,可以定义和使用mfc的诊断宏,采用mfc
debug库,对速度没有优化。
一、debug
和
release
编译方式的本质区别
debug
通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。release
称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。
debug
和
release
的真正秘密,在于一组编译选项。下面列出了分别针对二者的选项(当然除此之外还有其他一些,如/fd
/fo,但区别并不重要,通常他们也不会引起
release
版错误,在此不讨论)
releaseådebugçåºå«
ä¸ãDebug å Release ç¼è¯æ¹å¼çæ¬è´¨åºå«
Debug é常称为è°è¯çæ¬ï¼å®å å«è°è¯ä¿¡æ¯ï¼å¹¶ä¸ä¸ä½ä»»ä½ä¼åï¼ä¾¿äºç¨åºåè°è¯ç¨
åºãRelease 称为åå¸çæ¬ï¼å®å¾å¾æ¯è¿è¡äºåç§ä¼åï¼ä½¿å¾ç¨åºå¨ä»£ç 大å°åè¿è¡é度
ä¸é½æ¯æä¼çï¼ä»¥ä¾¿ç¨æ·å¾å¥½å°ä½¿ç¨ã
Debug å Release ççæ£ç§å¯ï¼å¨äºä¸ç»ç¼è¯é项ãä¸é¢ååºäºåå«é对äºè çé项
ï¼å½ç¶é¤æ¤ä¹å¤è¿æå ¶ä»ä¸äºï¼å¦/Fd /Foï¼ä½åºå«å¹¶ä¸éè¦ï¼é常ä»ä»¬ä¹ä¸ä¼å¼èµ· Rele
ase çé误ï¼å¨æ¤ä¸è®¨è®ºï¼
Debug çæ¬ï¼
/MDd /MLd æ /MTd ä½¿ç¨ Debug runtime library(è°è¯çæ¬çè¿è¡æ¶å»å½æ°åº)
/Od å ³éä¼åå¼å ³
/D "_DEBUG" ç¸å½äº #define _DEBUG,æå¼ç¼è¯è°è¯ä»£ç å¼å ³(主è¦é对
assertå½æ°)
/ZI å建 Edit and continue(ç¼è¾ç»§ç»)æ°æ®åºï¼è¿æ ·å¨è°è¯è¿
ç¨ä¸å¦æä¿®æ¹äºæºä»£ç ä¸ééæ°ç¼è¯
/GZ å¯ä»¥å¸®å©æè·å åé误
/Gm æå¼æå°åéé¾æ¥å¼å ³ï¼åå°é¾æ¥æ¶é´
Release çæ¬ï¼
/MD /ML æ /MT 使ç¨åå¸çæ¬çè¿è¡æ¶å»å½æ°åº
/O1 æ /O2 ä¼åå¼å ³ï¼ä½¿ç¨åºæå°ææå¿«
/D "NDEBUG" å ³éæ¡ä»¶ç¼è¯è°è¯ä»£ç å¼å ³(å³ä¸ç¼è¯assertå½æ°)
/GF å并éå¤çå符串ï¼å¹¶å°å符串常éæ¾å°åªè¯»å åï¼é²æ¢
被修æ¹
å®é ä¸ï¼Debug å Release 并没ææ¬è´¨ççéï¼ä»ä»¬åªæ¯ä¸ç»ç¼è¯é项çéåï¼ç¼è¯
å¨åªæ¯æç §é¢å®çé项è¡å¨ãäºå®ä¸ï¼æ们çè³å¯ä»¥ä¿®æ¹è¿äºé项ï¼ä»èå¾å°ä¼åè¿çè°
è¯çæ¬ææ¯å¸¦è·è¸ªè¯å¥çåå¸çæ¬ã
äºãåªäºæ åµä¸ Release çä¼åºé
æäºä¸é¢çä»ç»ï¼æ们åæ¥éä¸ªå¯¹ç §è¿äºé项çç Release çé误æ¯ææ ·äº§çç
1. Runtime Libraryï¼
2. ä¼åï¼è¿ç±»é误主è¦æ以ä¸å ç§ï¼
(1) 帧æé(Frame Pointer)çç¥ï¼ç®ç§° FPO ï¼ï¼å¨å½æ°è°ç¨è¿ç¨ä¸ï¼ææè°ç¨ä¿¡æ¯
ï¼è¿åå°åãåæ°ï¼ä»¥åèªå¨åéé½æ¯æ¾å¨æ ä¸çãè¥å½æ°ç声æä¸å®ç°ä¸åï¼åæ°ãè¿
åå¼ãè°ç¨æ¹å¼ï¼ï¼å°±ä¼äº§çé误ââââä½ Debug æ¹å¼ä¸ï¼æ ç访é®éè¿ EBP å¯åå¨
ä¿åçå°åå®ç°ï¼å¦æ没æåçæ°ç»è¶çä¹ç±»çé误ï¼ææ¯è¶çâä¸å¤âï¼ï¼å½æ°é常è½
æ£å¸¸æ§è¡ï¼Release æ¹å¼ä¸ï¼ä¼åä¼çç¥ EBP æ åºåæéï¼è¿æ ·éè¿ä¸ä¸ªå ¨å±æé访é®æ
å°±ä¼é æè¿åå°åé误æ¯ç¨åºå´©æºãC++ ç强类åç¹æ§è½æ£æ¥åºå¤§å¤æ°è¿æ ·çé误ï¼ä½å¦
æç¨äºå¼ºå¶ç±»å转æ¢ï¼å°±ä¸è¡äºãä½ å¯ä»¥å¨ Release çæ¬ä¸å¼ºå¶å å ¥ /Oy- ç¼è¯é项æ¥å ³
æ帧æéçç¥ï¼ä»¥ç¡®å®æ¯å¦æ¤ç±»é误ã
(2) volatile ååéï¼volatile åè¯ç¼è¯å¨è¯¥åéå¯è½è¢«ç¨åºä¹å¤çæªç¥æ¹å¼ä¿®æ¹
ï¼å¦ç³»ç»ãå ¶ä»è¿ç¨å线ç¨ï¼ã
(3) åéä¼åï¼ä¼åç¨åºä¼æ ¹æ®åéç使ç¨æ åµä¼ååéãä¾å¦ï¼å½æ°ä¸æä¸ä¸ªæªè¢«
使ç¨çåéï¼å¨ Debug çä¸å®æå¯è½æ©çä¸ä¸ªæ°ç»è¶çï¼èå¨ Release çä¸ï¼è¿ä¸ªåé
å¾å¯è½è¢«ä¼åè°ï¼æ¤æ¶æ°ç»è¶çä¼ç ´åæ ä¸æç¨çæ°æ®ãå½ç¶ï¼å®é çæ åµä¼æ¯è¿å¤æå¾
å¤ãä¸æ¤æå ³çé误æï¼
3. _DEBUG ä¸ NDEBUG ï¼å½å®ä¹äº _DEBUG æ¶ï¼assert() å½æ°ä¼è¢«ç¼è¯ï¼è NDEBUG æ¶ä¸
被ç¼è¯ãé¤æ¤ä¹å¤ï¼VC++ä¸è¿æä¸ç³»åæè¨å®ãè¿å æ¬ï¼
ANSI C æè¨ void assert(int expression );
C Runtime Lib æè¨ _ASSERT( booleanExpression );
_ASSERTE( booleanExpression );
MFC æè¨ ASSERT( booleanExpression );
VERIFY( booleanExpression );
ASSERT_VALID( pObject );
ASSERT_KINDOF( classname, pobject );
ATL æè¨ ATLASSERT( booleanExpression );
æ¤å¤ï¼TRACE() å®çç¼è¯ä¹å _DEBUG æ§å¶ã
4. /GZ é项ï¼è¿ä¸ªé项ä¼å以ä¸è¿äºäº
(1) åå§åå åååéã
(2) éè¿å½æ°æéè°ç¨å½æ°æ¶ï¼ä¼éè¿æ£æ¥æ æééªè¯å½æ°è°ç¨çå¹é æ§ãï¼é²æ¢å
å½¢ä¸å¹é ï¼
(3) å½æ°è¿ååæ£æ¥æ æéï¼ç¡®è®¤æªè¢«ä¿®æ¹.
ä¸ãææ ·âè°è¯â Release ççç¨åº
1. åé¢å·²ç»æè¿ï¼Debug å Release åªæ¯ä¸ç»ç¼è¯é项çå·®å«ï¼å®é ä¸å¹¶æ²¡æä»ä¹
å®ä¹è½åºåäºè ãæ们å¯ä»¥ä¿®æ¹ Release ççç¼è¯é项æ¥ç¼©å°é误èå´ãå¦ä¸æè¿°ï¼å¯ä»¥
æ Release çé项é个æ¹ä¸ºä¸ä¹ç¸å¯¹ç Debug é项ï¼å¦ /MD æ¹ä¸º /MDdã/O1 æ¹ä¸º /Od
ï¼æè¿è¡æ¶é´ä¼åæ¹ä¸ºç¨åºå¤§å°ä¼åã注æï¼ä¸æ¬¡åªæ¹ä¸ä¸ªé项ï¼çæ¹åªä¸ªé项æ¶é误æ¶
失ï¼å对åºè¯¥é项ç¸å ³çé误ï¼é对æ§å°æ¥æ¾ãè¿äºéé¡¹å¨ Project\Settings... ä¸é½å¯
以ç´æ¥éè¿å表éåï¼é常ä¸è¦æå¨ä¿®æ¹ãç±äºä»¥ä¸çåæå·²ç¸å½å ¨é¢ï¼è¿ä¸ªæ¹æ³æ¯ææ
æçã
2.ä½ ä¹å¯ä»¥å Debug ä¸æ ·è°è¯ä½ ç Release çï¼åªè¦å å ¥è°è¯ç¬¦å·ãå¨ Project/S
ettings... ä¸ï¼éä¸ Settings for "Win Release"ï¼éä¸ C/C++ æ ç¾ï¼Category é
Generalï¼Debug Info é Program Databaseãåå¨ Link æ ç¾ Project options æå
å ä¸ "/OPT:REF" (å¼å·ä¸è¦è¾)ã