5

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
)
4

2 に答える 2

7

例外処理には、Sun Studio C++ ツール チェーンと Gnu C++ の間で異なるライブラリとリンカーのサポートが必要です (この方法では、2 つのツール チェーン間で異なることをすでに指摘した名前マングリングに似ています)。「C」リンケージを使用しても、ここでは役に立ちません。リンク先の関数の実装は、その例外処理機能に依存するためです。通常、同じ実行可能ファイル内で 2 つの異なるツール チェーンでビルドされた C++ コードを使用することはできません。

Sun Studio とのみ互換性のあるクローズド ソース ライブラリを使用しているために Sun Studio を使用する必要がある場合、おそらく最も簡単な方法は、「GNU C++ でのみビルドする」ライブラリを取得して、Sun C++ コンパイラでビルドすることです。そのライブラリがオープンソースであること。これは簡単なことではなく、ライブラリの作成者からサポートを受ける必要があるかもしれません。私は必要に応じて、Sun コンパイラを正しいフラグで呼び出す GNU C++ コマンドのような小さなスクリプトを作成することで、これを実行しました。

それが問題にならない場合は、使用しようとしているライブラリをサービスでラップし、ある種の RPC メカニズムを使用して、Sun Studio のコンパイル済みコードからライブラリにアクセスする必要があります。

編集:リンクされているライブラリは特にブーストされているため、この質問が役立つ場合があります。要約すると、Boost の一部は、お使いのバージョンの Sun コンパイラで構築される可能性があります。

于 2014-12-15T18:23:08.457 に答える