メモの日々


2013年05月21日(火) [長年日記]

インテルコンパイラ13はソースファイルの拡張子に依り動作が変わるみたい

インテルコンパイラを使っていてはまったのでメモ。

#include <iostream>
#include <stdexcept>

int main()
try
{
    throw std::runtime_error("throw !");
} catch (...) {
    std::cout << "catch !" << std::endl;
}

上のC++のソースコードを「icpc (ICC) 13.0.1 20121010」でコンパイルして実行すると

terminate called after throwing an instance of 'std::runtime_error'
  what():  throw !

と出力された。例外がcatchされていない。

長いこと調べて(調べていたのはもっと巨大なプログラム)分かったのは、ソースファイルの拡張子が .c だと上のようになるということ。拡張子を .cpp にすれば

catch !

と表示される。これが結論。

…なんだけど、拡張子が .c でも、別のオブジェクトファイルをリンクするとcatchしてくれたりする。どんなオブジェクトファイルをリンクしたらそうなるのかは分からなかった。バグっぽい動作に見えるので、最新のインテルコンパイラでは挙動が違うかも。

(追記)

拡張子が .c でも、-xオプションで c++ を指定すれば例外がcatchされるようになった。

% icpc --version
icpc (ICC) 13.0.1 20121010
Copyright (C) 1985-2012 Intel Corporation.  All rights reserved.

% icpc main.c; ./a.out
terminate called after throwing an instance of 'std::runtime_error'
  what():  throw !

% icpc -xc++ main.c; ./a.out
catch !

うーん、せめて -xc++ を付けない場合にはコンパイルエラーになってくれればいいのに。

-xオプションはGCCにもあるけれど、GCCの場合はg++を使えば拡張子が.cであってもちゃんと動作する。

% g++ --version
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

% g++ main.c; ./a.out
catch !