• 网络学院
  • IT资讯
  • 操作系统
  • 网络技术
  • 软件应用
  • 办公软件
  • 编程技术
  • 网站架设
  • 数据库类
  • 平面设计
  • 多媒体类
  • 游戏资讯
  • 教学论文
  • 认证考试
VC6.0如何让new失败后抛出异常
  站点:
  • 首 页
  • 最新软件
  • 文章教程
  • 国内软件
  • 国外软件
  • 绿色软件
  • 源码下载
  • 字体下载
VC6.0如何让new失败后抛出异常
软件发布 VC6.0如何让new失败后抛出异常
网络软件 系统工具 应用软件 联络聊天 图形图像 多媒体类 行业软件 游戏娱乐 编程开发 安全相关 教育教学 数码软件 绿软下载
热门软件: QQ 瑞星 pplive e话通 木马克星 千千静听 office2000 五笔字根 Photoshop 视频分割
返回文章教程首页 >> 文章首页 >> 编程技术 >> VC教程 >> VC6.0如何让new失败后抛出异常

VC6.0如何让new失败后抛出异常

添加时间: 2006-2-11 0:00:40  作者: VC教程  阅读次数:498   来源: http://www.d9soft.com

        C标准库一起使用,比如libcp.lib与libc.lib搭配。另外,VC6.0在new.cpp还定义了一个operator new,原型如下 :

void * operator new( unsigned int cb )

  而new.cpp对应的目标模块却是被打包进C标准库中的(是不是有点奇怪?)。

  一般来说,程序员不会显式指定链接C++标准库,可是当程序中确实使用了标准C++库时链接器却能聪明地把相应的C++标准库文件加进输入文件列表,这是为什么?其实任何一个C++标准头文件都会直接或间接地包含use_ansi.h文件,打开它一看便什么都清楚了(源码之前,了无秘密) :

/***
*use_ansi.h - pragmas for ANSI Standard C++ libraries
*
* Copyright (c) 1996-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
* This header is intended to force the use of the appropriate ANSI
* Standard C++ libraries whenever it is included.
*
* [Public]
*
****/


#if _MSC_VER > 1000
#pragma once
#endif

#ifndef _USE_ANSI_CPP
#define _USE_ANSI_CPP

#ifdef _MT
#ifdef _DLL
#ifdef _DEBUG
#pragma comment(lib,"msvcprtd")
#else // _DEBUG
#pragma comment(lib,"msvcprt")
#endif // _DEBUG

#else // _DLL
#ifdef _DEBUG
#pragma comment(lib,"libcpmtd")
#else // _DEBUG
#pragma comment(lib,"libcpmt")
#endif // _DEBUG
#endif // _DLL

#else // _MT
#ifdef _DEBUG
#pragma comment(lib,"libcpd")
#else // _DEBUG
#pragma comment(lib,"libcp")
#endif // _DEBUG
#endif

#endif // _USE_ANSI_CPP

  现在我们用实际代码来测试一下new会不会抛出异常,建一个test.cpp源文件:

// test.cpp
#include
#include

using namespace std;

class BigClass
{
 public:
  BigClass() {}
  ~BigClass(){}
  char BigArray[0x7FFFFFFF];
};

int main()
{
 try
 {
  BigClass *p = new BigClass;
 }
 catch( bad_alloc &a)
 {
  cout << "new BigClass, threw a bad_alloc exception" << endl;
 }

 BigClass *q = new(nothrow) BigClass;
 if ( q == NULL )
  cout << "new(nothrow) BigClass, returned a NULL pointer" << endl;
  try
  {
   BigClass *r = new BigClass[1];
  }
  catch( bad_alloc &a)
  {
   cout << "new BigClass[1], threw a bad_alloc exception" << endl;
  }
 return 0;
}
根据VC6.0编译器与链接器的做法(请参考《为什么会出现LNK2005"符号已定义"的链接错误?》),链接器会首先在C++标准库中解析符号,然后才是C标准库,所以如果开发者没有自定义operator new的话最后程序链接的应该是C++标准库中newop.obj和newop2.obj模块里的代码。可是程序运行的结果却是:

new(nothrow) BigClass, returned a NULL pointer

  显然程序始终未抛出bad_alloc异常。单步跟踪观察,发现第1个和第3个new实际上调用了new.cpp里的operator new,而第二个new(nothrow)则正确地调用了newop2.cpp定义的版本。很难理解是吧?但是当你用

dumpbin /SYMBOLS libcp.lib

  dump出libcp.lib所有的符号信息时,你会发现其中的newop.obj模块没有定义任何符号(其它版本也一样)。不可思议!newop.cpp的实现代码明明写在那儿,怎么会....?让我们再仔细看看newop.cpp,咦,operator new的定义被包裹在一个#if...#endif块中:

#if !defined(_MSC_EXTENSIONS)

...
...

void *__cdecl operator new(size_t size) _THROW1(_STD bad_alloc)
{
...
...
}

#endif

  原来需要_MSC_EXTENSIONS宏未定义,实现代码才是有效的啊。那么这个宏是什么意思?其实Visual C++在语言层面上对ANSI C标准做了一些特殊的扩展,定义_MSC_EXTENSIONS意味着编译器支持这样的扩展,没有定义它编译器就会严格按照ANSI C标准来编译程序。实际上如果指定了编译选项/Ze编译器就会自动定义这个宏,指定/Za则不会,而且/Ze是缺省选项。作者猜想Visual Studio的开发人员在build标准C++库时很可能没有指定/Za,导致newop.cpp中的operator new定义被无情抛弃。是他们的疏漏吗?我看未必,大家可以试试用/Za选项去编译那些标准库文件,看看有多少编译不通过。VC标准库的实现用了很多微软扩展的语言特性,不指定/Za是情有可原的,我不明白的是newop.cpp的作者(好象是P.J. Plauger老人家)为什么会加上一个如此愚蠢的"#if !defined(_MSC_EXTENSIONS)",因为实在看不出这个operator new定义与_MSC_EXTENSIONS有什么冲突的地方。

  既然标准C++库里的newop.obj是个空壳,那我们就只好自己动手丰衣足食了。把newop.cpp和dbgint.h(都在VC98\crt\src目录下)拷贝到test.cpp所在的目录,并将newop.cpp中的

#include

  改成

#include "dbgint.h"

  然后用

cl /c /Za /D_CRTBLD newop.cpp

  编译它。/D_CRTBLD定义了_CRTBLD宏,为什么这么做呢?因为dbgint.h属于内部头文件,VC不希望应用程序用到它,便在文件中埋伏了这么一段:

#ifndef _CRTBLD
/*
* This is an internal C runtime header file. It is used when building
* the C runtimes only. It is not to be used as a public header file.
*/
#error ERROR: Use of C runtime library internal header file.
#endif /* _CRTBLD */

  可我们确确实实是想build标准库(的一部分),所以只好强行突破这个限制了。然后编译test.cpp:

cl /c /GX test.cpp

  最后进行链接:

link test.obj newop.obj

  这时再运行test.exe输出的结果就是

new BigClass, threw a bad_alloc exception
new(nothrow) BigClass, returned a NULL pointer
new BigClass[1], threw a bad_alloc exception

  值得庆幸的是虽然VC6.0如此弱智,但VC7.1却表现良好,原因是VC7.1的newop.cpp和newaop.cpp(数组版)取消了那个愚的"#if !defined(_MSC_EXTENSIONS)",于是标准C++库中的newop.obj和newaop.obj模块都实实在在地有了相应代码。另外,nothrow版的定义也分别转移到了newopnt.cpp和newaopnt.cpp中。

 

上下文章:

 

上一篇文章: 人月团圆:用C实现的爱情宣言 下一篇文章: C++箴言:公开继承模拟“is-a”

相关文章:

  • 教你如何用零框架技术加密网页
  • PS教程:看看如何用Photoshop把照片演变成水墨画
  • Photoshop教程:教你如何创出发丝的炫彩莹亮效果
  • 魔兽世界:如何更大限度的利用奥冲循环
  • 教你如何用PhotoImpact 来制作逼真的温度计

相关软件:

  • 如何配置dns系统虚拟域名的配置和设置方法(PDF)
  • 如何使用Access 2000 中文版(PDG)

 

快速导航

  • 网络学院
  • 精品汇聚
  • 字体下载
  • 教程下载
  • ASP源码
  • PHP源码
  • Net源码
  • JSP 源码

编程技术分类导航

  • ASP & ASP.NET教程
  • PHP教程
  • JSP教程
  • C/C++教程
  • VB & VB.NET教程
  • VC教程
  • Delphi教程
  • BCB教程
  • VFP教程
  • PB教程
  • JAVA教程
  • XML教程
  • C#教程
  • CGI教程

本类经典文章推荐

  • VC++之Button控件
  • VC++之Static Box控件
  • VC++之Edit Box控件
  • VC++之Static Box控件
  • VC++之Edit Box控件
  • VC++之Scroll Bar
  • VC++之Scroll Bar
  • VC++之List Box/Check List Box控...
  • VC++ Combo Box/Combo Box Ex控件
  • VC++ List Ctrl控件

VC教程阅读排行

  • VC++之List Box/Check List Box控...
  • VC++ List Ctrl控件
  • VC++ Combo Box/Combo Box Ex控件
  • VC++之Button控件
  • VC++之Tab Ctrl控件
  • VC++之Edit Box控件
  • VC++之Edit Box控件
  • VC遍历整个目录树查找文件
  • VC++之Scroll Bar
  • 深入编程:控制面板知多少?

编程技术阅读总排行

  • VB入门教程之一
  • Java连接数据库实例
  • 第二章 PowerBuilder 入门之创建新...
  • VC++之List Box/Check List Box控...
  • 第一章 什么是PowerBuilder
  • VC++ List Ctrl控件
  • VC++ Combo Box/Combo Box Ex控件
  • 学C++不得不看的一篇文章
  • VB入门教程之二
  • VC++之Button控件

广告位置

字母检索 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 回到顶部

关于我们 | 版权声明 | 免责条款 | 广告联系 | 软件发布 | 下载帮助 | 下载排行 | 网站地图 | 特别鸣谢 | 友情连接

copyright; 2005-2008 D9soft.com 第九软件网 版权所有