程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> VC6.0中如何讓new操作失敗後拋出異常?

VC6.0中如何讓new操作失敗後拋出異常?

編輯:vc教程

標准C++規定new一個對象時如果分配內存失敗就應拋出一個std::bad_alloc異常,如果不希望拋出異常而僅僅傳回一個NULL指針,可以用new的無異常版本:new(nothrow)。

  VC6.0在<new>頭文件中聲明了這兩種Operator new操作符:

void *__cdecl Operator new(size_t) _THROW1(std::bad_alloc);
void *__cdecl Operator new(size_t, const std::nothrow_t&) _THROW0();

  並分別定義在newop.cpp和newop2.cpp中。而_THROW0和_THROW1則是兩個宏,在Include目錄的xstddef文件中定義:

#define _THROW0() throw ()
#define _THROW1(x) throw (x)

  newop.cpp和newop2.cpp對應的目標模塊被打包進標准C++庫中。標准C++庫有若干個版本: libcp.lib(單線程靜態版)、libcpd.lib(單線程靜態調試版)、libcpmt.lib(多線程靜態版)、libcpmtd.lib(多線程靜態調試版)、msvcprt.lib(多線程動態版的導入庫),msvcprtd.lib(多線程動態調試版的導入庫),這些庫與相應版本的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 <new>
#include <iOStream>

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裡的

[1] [2] 下一頁

  1. 上一頁:
  2. 下一頁:
欄目導航
Copyright © 程式師世界 All Rights Reserved