Sun Studio でアプリケーションを構築する必要があります。このアプリケーションは、Gnu C++ でのみビルドできる共有ライブラリを使用します。共有ライブラリには C インターフェイスがあるため、Sun コンパイラからコードを呼び出すことができます (これは、名前マングリングの問題を回避するためです。この質問も参照してください)。
例外処理以外はすべて正常に動作します。共有ライブラリで例外がスローされると、プログラムはセグメンテーション違反を起こします。これは、メイン プログラムが Sun Studio コンパイラを使用してコンパイルされた場合にのみ発生します。以下の最小限の例を Gnu C++ コンパイラでコンパイルすると、プログラムは正常に動作し、共有ライブラリが例外を検出します。
プラン A: 動的にリンクする セットアップの図を次に示します。
GCC SOLARIS STUDIO
shared
c_layer.so <----- application
(no exceptions) (uses exceptions sol studio)
|
| use flag -static -static-libstdc++ -static-lib-gcc
v
gcc_only_lib.so
libstdc++.so
(uses gcc exceptions)
結果: 例外がスローされるとセグメンテーション違反が発生します (以下のコードを参照)。
プラン B: 静的にリンクする
上記と同じですが、c_layer.a をビルドします
結果:
ファイル __cxa_allocate_exception libs/cInterface/libcInterface.a(c_layer.cpp.o) std::string::~std::basic_string () libs/cInterface/libcInterface.a(c_layer.cpp.o) の未定義の最初の参照シンボル/cInterface/libcInterface.a(c_layer.cpp.o) __cxa_free_exception libs/cInterface/libcInterface.a(c_layer.cpp.o) __cxa_begin_catch libs/cInterface/libcInterface.a(c_layer.cpp.o) __cxa_throw libs/cInterface/libcInterface. a(c_layer.cpp.o)
質問:例外処理が Sun Studio で機能しないのはなぜですか?
次のように gcc ランタイムを強制すると:
LD_PRELOAD=/usr/sfw/lib/amd64/libgcc_s.so ./example
それは別様にクラッシュします:
$> 'std::runtime_error' のインスタンスをスローした後に呼び出される終了 $> 再帰的に呼び出される終了
(dbx) ここで 1__lwp_sigqueue(0x1、0x6、0xffffc1000bae5060、0xffffff80ffffffbbff51e70a [2] thr_kill(0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0、0x0) 0x0、0x0)、0xffff80ffbf4c291d で [4] 中止 (0x0、0x0、0x0、0x0、0x0、0x0)、0xffff80ffbf497ff2 で [5] __gnu_cxx::__verbose_terminate_handler(0x0、0x0、0x0、0x0、0x0) 9 で[6] __cxxabiv1::__terminate(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xffff80ffbd9dbd5b [7] std::terminate(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xffff80ffbd9dbda3 [8] __cxa_rethrow (0x0, 0x0, 0x0, 0x0, 0x0, 0x0), 0xffff80ffbd9dc02d [9] __gnu_cxx::__verbose_terminate_handler(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), 0xffff80ffbd9de8d4 [10] __cxxterminate 0(__x0, 0x0: 、0x0、0x0、0x0、0x0)、0xffff80ffbd9dbd5b [11] std::terminate(0x0、0x0, 0x0, 0x0, 0x0, 0x0), 0xffff80ffbd9dbda3 [12] で、0xffff80ffb9991116 => [14] main(argc = 1、argv = 0xffff80ffbffffa78)、「exampleMain.cpp」の6行目
問題を再現するための最小限の例を次に示します。
例Main.cpp:
#include <clayer.h>
#include <stdio.h>
int main(int argc, char **argv)
{
if (!clayerCall())
printf("got exception\n");
else
printf("OK\n");
}
共有ライブラリ ヘッダー:
extern "C" {
bool clayerCall();
} // end extern "C"
共有ライブラリ ソース:
#include "clayer.h"
#include <exception>
#include <stdexcept>
#include <stdio.h>
extern "C" {
bool clayerCall()
{
try
{
throw std::runtime_error("hhh");
return true;
}
catch (std::exception &ex)
{
return false;
}
}
} // end extern c
cmake ファイルは次のようになります。
実行可能ファイルの
project(exampleMain)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_BUILD_TYPE Debug)
add_definitions(-m64 -fPIC)
include_directories(../stackoverflow)
link_directories (
../stackoverflow
)
add_executable(example exampleMain.cpp)
target_link_libraries(
example
stdc++
clayer
)
ライブラリ用
project(clayer)
cmake_minimum_required(VERSION 2.8)
cmake_policy(VERSION 2.8)
set(CMAKE_BUILD_TYPE Debug)
add_library(
clayer SHARED
clayer.cpp
)