Debug版本下能运⾏⽽Release下不能运⾏的问题总结
引⾔
如果在您的开发过程中遇到了常见的错误,或许您的Release版本不能正常运⾏⽽Debug版本运⾏⽆误,那么我推荐您阅读本⽂:因为并⾮如您想象的那样,Release版本可以保证您的应⽤程序可以象Debug版本⼀样运⾏。如果您在开发阶段完成之后或者在开发进⾏⼀段时间之内从来没有进⾏过Release版本测试,然⽽当您测试的时候却发现问题,那么请看我们的调试规则1:
规则1:
  经常性对开发软件进⾏Debug和Release版本的常规测试. 测试Release版本的时间间隔越长,排除问题的难度越⼤,⾄少对Release版本进⾏每周1
不要随意删除Release
ASSERT和TRACE在Release
continue语句执行过程
  例如: ASSERT(m_ImageList.Create(MAKEINTRESOURCE(IDB_IMAGES), 16, 1, RGB(255,255,255))); 这样的代码在Debug模式不会出错,图像列表也⾃动创建了,然⽽在Release版本呢?后继使⽤m_ImageList对象只会造成程序的Crash!,因此ASSERT宏中尽量使⽤逻辑运算符作为验证。
规则 2:
  不要将代码放置在仅在某种编译选项中执⾏的地⽅,对于使⽤_DEBUG等编译选项宏内部的代码必须不影响整个程序的使⽤。
规则 3:
  不要使⽤规则2作为评判标准来删除ASSERT宏,ASSERT宏是个有⽤的⼯具,但容易使⽤错误. 使Debug编译模式接近Release模式如果您的Release版本存在的问题是由代码被编译器⾃动排除造成的,那么通过这个⽅法您的问题可能会重现. ⼀些问题的产⽣可能是由于不同编译选项之间预定义符号造成的,因此您可以更改编译模式下的预定义符号,从⽽使您的Debug模式接近Release模式,观察错误是否产⽣,
  更改编译预定义符号⽅法如下:
   a.. Alt-F7打开项⽬设置,在C++/C 页⾯,选择"General"类别,更改"_DEBUG"符号为"NDEBUG".
b.. 在C++/C 页⾯, 选择"Preprocessor"类别,添加预定义符号"_DEBUG"到"Undefined Symbols"栏.
c..
  使⽤"Rebuild All"重新编译如果通过上⾯设置,您在Release编译模式下⾯的问题在Debug模式下重现,那么请您依据以下步骤对您的代码进⾏修改:
   a.. 查ASSERT排除其中的所有重要执⾏语句,或者将ASSERT修改为VERIFY.
   b.. 检查"#ifdef _DEBUG" 内所有代码,排除Release模式使⽤的代码.
   c.. 查TRACE 排除其中的所有重要执⾏语句. TRACE和ASSERT⼀样,仅在Debug模式下编译. 如果通过上⾯修改更正了您在Debug模式下的问题,那么您可以重新编译Release模式,⾮常有可能您可以解决先前存在的问题!. 错误的假定造成编译模式错误您是否经常性的假定您的变量或者对象被初试化成某个指定的值(可能0)?您是否假定你所有关联到的资源在应⽤程序中都存在?这些也是Debug和Release模式下不同问题产⽣的原因。
规则 4:
  除⾮您在代码中对变量进⾏初始化,否则不能作出如上假定. 包括全局变量,⾃动变量,申请对象和new对象. 这种情况还常常发⽣在内存顺序的问题,记得原来使⽤结构体的时候为了使⽤⽅便,⽐较两个结构体对象使⽤memcmp,在Debug版本⼯作正常,⽽Release版本计算出错误的解,看来的确不能进⾏错误的假定!
规则 5:
  确保删除资源的所有引⽤都被删除,例如resource.h中的定义. 软件开发中,不同编译版本对变量和内存的初始化是不同的. 如果您假定变量初始化为0,那么在Win9x系统的Release模式下,会出现异常现象。因此对所有变量,内存显式清0是较为安全的做法. 如果您引⽤了已经被删除的资源,您的Debug版本可以正常⼯作,但是Release版本可能会crash. 您是否相信编译器? 编译器警告级别和编译噪⾳有着相当⼤的关系. 通过提⾼编译器警告级别可增加程序隐藏问题暴露的机会.通常设置警告级别在"Level 3"或者 "Level 4".编译并解决所有警告,这是发布Release版本应⽤程序的⼀个很好的建议.这能暴露会使您的应⽤程序出现问题的很多初始化问题和其它潜在的错误.
规则 6:
  开始项⽬之前先将编译警告级别设置在"Level 3" 或者 "Level 4" ,登记代码之前确保消灭所有警告!. 总结报告编译模式下的调试曾经不⽌⼀次的听到⼀些VC开发者说Release模式下⾯不能进⾏调试,幸
运的是:通过相应设置,可以在Release模式进⾏调试,因此那只不过是⼀个以讹传讹的荒谬说法⽽已。
规则 7:
  当前⾯所有的⽅法都⽆效的时候,在Release模式下⾯进⾏调试. Release模式可以进⾏调试,
  第⼀步是打开符号表:
  a.. Alt-F7打开项⽬设置,在C++/C 页⾯,选择"General"类,修改Debug Info setting 为 "Program Database".
b.. 在"Link" 页⾯,选择"Generate Debug Info".
c.. "Rebuild All"
  这些设置将允许您在Release模式下保留符号表,您也可以同时考虑以下设置:
  a.. 调试Release版本应⽤程序,您可以关闭优化选项.
  b.. 如果在Release模式下⾯不能设置断点,添加指令"__asm {int 3}" 可以使您的应⽤程序在该⾏停⽌
(确定在发布应⽤程序时候排除这些代码).
  在Release模式进⾏调试的⼏个限制.
  a.. 最⼤的问题在于您不能跟踪到MFC函数内部,原因在于Release版本的MFC动态链接库不包含调试信息和符号表.
  b.. 同上,想要调试调⽤的dll,您必须给它们全部加上调试信息和符号表. 编译器⽣成了错误的代码? 或许有的时候您会发现VC++编译器⽣成了’问题代码’,然⽽坦率的讲,⼈们通常抱怨的太早.您可以在Release模式下⾯关闭优化选项来进⾏测试. 如果这个操作解决了您的问题,或许您的编码习惯存在问题. 信不信由你, 极其可能在您的编码中存在模棱两可的求解或者看起来似乎正确,某些条件下也是正确的情况.
  举个例⼦,下⾯的代码在Debug模式似乎⼀切’正常’,⽽在Release模式下⾯却会出错!
  #include int* func1(){int retval = 5;return &retval;} int main(int argc, char* argv[]){printf("%d/n", *func1());return 0;}我相信⼤多数程序员尤其是初学者容易遇到此类情况的。
规则 8:
  如果关闭Release模式的优化选项可以使您的应⽤程序运⾏正常,⽽打开优化选项则出现问题的化,原因多半在于您的不良编码习惯造成的. 这意味着必须仔细检查您的代码,清理出那些错误的假设,悬空指针等等. 等同的这告诉您,在Debug模式和关闭优化选项的Release模式下您的应⽤程序⼯作正常全是因为系统隐含的运⽓,您必须着⼿更正存在隐患的代码,否则在⽇后可能会造成巨⼤的损失。
规则 9:
  如果您已经彻底检查了您的代码,并且没有发现问题,那么您最好逐个打开优化选项将产⽣错误的原因限制在某个范围之内. BTW- 以上问题代码由C++编译器⾃动检出. 如果您已经遵循规则 6 您或许在前⾯环节中已经解决了这些问题. 凭我的开发经验,编译器极少会产⽣错误的代码(当然要注意接⼝程序边界对齐的问题).通常在使⽤模板类时候VC6编译器或许会产⽣断⾔ASSERT错误,这种情况您只需更新补丁即可解决。
  最后的思考在⽇常编码中只需稍微增加⼀点严格的检测,便能有效的避免新的Debug -v- Release模式问题的产⽣,以下是我的⼀些经验。
  1. 取出(check out)需要修改的代码。
  2. 修改代码,排除所有警告,编译Debug和Release版本.
  3. 详细测试新代码,即单步调试新代码段之后进⼊⼯作代码,确保代码⽆误.
  4. 更正所有问题.
  5. 确认⽆误之后将新代码登记⼊库(check in).
  6. 对登记⼊库的代码进⾏全新的编译,确保新登记代码与其它代码融合.
  7. 重新详细测试代码.
  8. 更正新问题(或许可以发现登记⼊库代码存在的问题) 严格按照以上步骤,您在设计开发过程中即可解决⼤量问题,避免在最后发布应⽤程序时候产⽣新的难以定位的问题.
后记本⽂是在我的开发历程中遇到Release版本应⽤程序发布,产⽣错误的时候苦苦求索得到的⼀些经验,原⽂来⾃于codeproject,经过本⼈润⾊,改写成为适合国内开发者的
⽂章,希望能对⼤家有⽤,谢谢!
==============================================================================================================================================================
  转载: Debug版本包括调试信息,所以要⽐Release版本⼤很多(可能⼤数百K⾄数M)。⾄于是否
需要DLL⽀持,主要看你采⽤的编译选项。如果是基于ATL的,则Debug
和Release版本对DLL的要求差不多。如果采⽤的编译选项为使⽤MFC动态库,则需要MFC42D.DLL等库⽀持,⽽Release版本需要MFC42.DLL⽀持。Release Build不对源代码
进⾏调试,不考虑MFC的诊断宏,使⽤的是MFC Release库,编译⼗对应⽤程序的速度进⾏优化,⽽Debug Build则正好相反,它允许对源代码进⾏调试,可以定义和使⽤MFC
的诊断宏,采⽤MFC Debug库,对速度没有优化。
⼀、Debug 和 Release 编译⽅式的本质区别 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 并没有本质的界限,他们只是⼀组编译选项的集合,编译器只是按照预定的选项⾏动。事实上,我们甚⾄可以修改这些选项,从⽽得到优化
过的调试版本或是带跟踪语句的发布版本。
⼆、哪些情况下 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 时不被编译。除此之外,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 控制。所有这些
断⾔都只在 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 版在动态分配内存的前后加⼊保护内存以防⽌越界访问),其中括号中的词是微软建议
的助记词。这样做的好处是这些值都很⼤,作为指针是不可能的(⽽且 32 位系统中指针很少是奇数值,在有些系统中奇数的指针会产⽣运⾏时错误),作为数值也很少遇到,
⽽且这些值也很容易辨认,因此这很有利于在 Debug 版中发现 Release 版才会遇到的错误。要特别注意的是,很多⼈认为编译器会⽤ 0 来初始化变量,这是错误的(⽽且这样
很不利于查错误)。
  (2) 通过函数指针调⽤函数时,会通过检查栈指针验证函数调⽤的匹配性。(防⽌原形不匹配)
  (3) 函数返回前检查栈指针,确认未被修改。(防⽌越界访问和原形不匹配,与第⼆项合在⼀起可⼤致模拟帧指针省略 FPO )通常 /GZ 选项会造成 Debug 版出错⽽
Release 版正常的现象,因为 Release 版中未初始化的变量是随机的,这有可能使指针指向⼀个有效地址⽽掩盖了⾮法访问。除此之外,/Gm /GF 等选项造成错误的情况⽐较
少,⽽且他们的效果显⽽易见,⽐较容易发现。
==============================================================================================================================================================
  在使⽤VC开发软件的过程中,正当要享受那种兴奋的时候突然发现: release与debug运⾏结果不⼀致,甚⾄出错,⽽release⼜不⽅便调试,真的是当头⼀棒啊,可是疼归疼,问题总要解决,下⾯将讲述⼀下我的两点经验,看看是不是其中之⼀:
  1. 变量。
  ⼤家都知道,debug跟release在初始化变量时所做的操作是不同的,debug是将每个字节位都赋成0xcc,⽽release的赋值近似于随机(我想是直接从内存中分配的,没有初始化过,但debug为什么不是0xff或0x00或其他什么的就不得⽽知了)。这样就明确了,如果你的程序中的某个变量没被初始化就被引⽤,就很有可能出现异常:⽤作控制变量将导致流程导向不⼀致;⽤作数组下标将会使程序崩溃;更加可能是造成其他变量的不准确⽽引起其他的错误。所以在声明变量后马上对其初始化⼀个默认的值是最简单有效的办法,否则项⽬⼤了你都没地⽅。代码存在错误在debug⽅式下可能会忽略⽽不被察觉到,如debug⽅式下数组越界也⼤多不会出错,在release中就暴露出来了,这个起来就⽐较难了:( 还是⾃⼰多加注意吧
  2. ⾃定义消息的消息参数。
  MFC为我们提供了很好的消息机制,更增加了⾃定义消息,好处我就不⽤多说了。这也存在debug跟release的问题吗?答案是肯定的。在⾃定义消息的函数体声明时,时常会看到这样的写法:afx_msg LRESULT OnMessageOwn(); 当你在多线程或进程间使⽤了消息传递时就会导致⽆效句柄之类的错误。这个原因就是消息体的参数没有添加,即应该写成:afx_msg LRESULT OnMessageOwn(WPARAM wparam, LPARAM lparam); (具体原因我也不太清楚,是不是因为调⽤时按着默认的参数多分配了
WPARAM+LPARAM的空间⽽破坏了应⽤程序的内存空间?还请⾼⼿多指点)
  避免的⽅法:
  1. 注意变量的初始化
  2. ⾃定义消息的标准写法
  3. 使⽤调试语句TRACE等时使⽤后最好注释掉
  4. 尽量使⽤try - catch(...)
   VERIFY 和 ASSERT 的区别:⼀个在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 it */ found = TRUE; break; } /* found it */ } 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(debu
g版以32bytes为单位分配),⽽在release版,分配给你的就是
24bytes(release版以8bytes为单位),所以在debug版中如果你写ele[6],可能不会有什么问题,⽽在release版中,就有ACCESS VIOLATE。
  II. ASSERT和VERIFY
    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版中就可以执⾏了。
  III. 参数问题:⾃定义消息的处理函数,必须定义如下: afx_msg LRESULT OnMyMessage(WPARAM, LPARAM); 返回值必须是HRESULT型,否则Debug会过,⽽Release出错
  IV. 内存分配保证数据创建和清除的统⼀性:如果⼀个DLL提供⼀个能够创建数据的函数,那么这个DLL同时应该提供⼀个函数销毁这些数据。数据的创建和清除应该在同⼀个层次上。
  VI. RELEASE板中的调试:
    1.将ASSERT() 改为 VERIFY() 。出定义在"#ifdef _DEBUG"中的代码,如果在RELEASE版本中需要这些代码请将他们移到定义外。查TRACE(...)中代码,因为这些代码在RELEASE中也不被编译。请认真检查那些在RELEASE中需要的代码是否并没有被便宜。
    2.变量的初始化所带来的不同,在不同的系统,或是在DEBUG/RELEASE版本间都存在这样的差异,所以请对变量进⾏初始化。
    3.是否在编译时已经有了警告?请将警告级别设置为3或4,然后保证在编译时没有警告出现. VII. 将Project Settings" 中 "C++/C " 项⽬下优化选项改为Disbale(Debug)。 
    1.此外对RELEASE版本的软件也可以进⾏调试,请做如下改动:
      在"Project Settings" 中 "C++/C " 项⽬下设置 "category" 为 "General" 并且将"Debug Info"设置为 "Program Database"。
      在"Link"项⽬下选中"Generate Debug Info"检查框。
      "Rebuild All" 如此做法会产⽣的⼀些限制:⽆法获得在MFC DLL中的变量的值。必须对该软件所使⽤的所有DLL⼯程都进⾏改动。
    2.另: MS BUG:MS的⼀份技术⽂档中表明,在VC5中对于DLL的"Maximize Speed"优化选项并未被完全⽀持,因此这将会引起内存错误并导致程序崩溃。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。