Entry

プログラミングメモ - new が失敗したときの扱い方

2008年12月02日

こちらの話から。new の失敗について,ちと思い出したんでメモ。

■newが失敗するとポインタにNULLが返ってきます。

#include <stdio.h>

void  main(){

    int*i;
    i=new int[1000000000];
    if(i==NULL){
        printf("new 失敗\n");
    }else{
        printf("new 成功\n");
    }
    delete[] i;
}
newの失敗

最後にまとめて delete するのはお作法的にまずかろう,とか思うんですけれど(delete NULL は安全だから,まぁいいっちゃいんだけど),それはさておき,見るのは i の中を見て new が成功したか判断しているところです。C では一般的な方法。

ここら辺は微妙に混乱するところなんだけれども,new したときに返値の NULL をアテにしていい(malloc(3) と同じようなエラー処理になる)処理系は,あたしの知る限り,VC6 標準の挙動だけだった気がします。上の例の場合,new は一切例外を投げず,NULL を返します。

ただ,VC6 でも MFC を使うと,new オペレータが上書きされて,例外を投げるようになります(GX オプションを付けてリンクする)。この場合,new が失敗した時点で例外が throw されてしまうので,用意したポインタに返値は代入されません。また,MFC の標準で投げられる例外は std::bad_alloc ではなく,CMemoryException になる。

んなもんで,new の失敗の扱い方は,こんな感じになります。p に NULL が渡るのか,参考のために p のアドレス値を出力しておきます。ちなみに,処理系は ICC(Intel C++ Compiler) 10 で,VC6 付属のコンパイラではありません。

#include <cstdio>
#include <afx.h>

int
_tmain(int argc, char* argv[], char* envp[]) {
    char* p;
    try {
        ::printf("%p\n", p);
        p = new char[0x7fffffffL];
        ::printf("success\n");
        ::printf("%p\n", p);
        delete[] p;
    }
    catch (CMemoryException* e) {
        e->Delete();
        ::printf("failed\n");
        ::printf("%p\n", p);
    }

    return 0;
}

実行結果はこんな感じ。p に NULL は入っていません。

C:\home\aian\Debug>sample.exe
CCCCCCCC
failed
CCCCCCCC

個人的に,C++ で new を使う場合,返値の NULL をアテにするのは,あまりやりたくなかったりします。ちゃんと例外を出させた方がすっきりしますしね。malloc(3) みたいに例外処理するにしても,NULL を返す処理系(前掲)と失敗したら元の値を変えない(ISO C++ ?)処理系があるので,受けるポインタは,はじめから NULL で初期化しておくのがいいんだと思います。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN