2016-09-18 13 views
2

SunのC++コンパイラに問題があります。私はオラクルのWorking with Pointers to Functions [from C++]を読んだ。その良い読書と、私はSunCCがこの分野のすべてのコンパイラの中で最も遵守しているという印象を受けました。警告(時代遅れ):extern "C" void(*)(int)にvoid(*)を割り当てる

テストコードは次のとおりで、24行目はnew_handler.sa_handler = (pfn ? pfn : &SignalHandler::NullHandler);です。三元演算子をアンロールすると、これは問題です:new_handler.sa_handler = pfn;

SunCC 5.11

$ /opt/solstudio12.2/bin/CC test.cxx 
"test.cxx", line 24: Warning (Anachronism): Assigning void(*)(int) to extern "C" void(*)(int). 
"test.cxx", line 58:  Where: While instantiating "SignalHandler<5, 0>::SignalHandler(void(*)(int), int)". 
"test.cxx", line 58:  Where: Instantiated from non-template code. 

SunCC 5.12

$ /opt/solarisstudio12.3/bin/CC test.cxx 
"test.cxx", line 24: Warning (Anachronism): Assigning void(*)(int) to extern "C" void(*)(int). 
"test.cxx", line 58:  Where: While instantiating "SignalHandler<5, 0>::SignalHandler(void(*)(int), int)". 
"test.cxx", line 58:  Where: Instantiated from non-template code. 

SunCC 5.13

$ /opt/solarisstudio12.4/bin/CC test.cxx 
"test.cxx", line 24: Warning (Anachronism): Using void(*)(int) to initialize extern "C" void(*)(int). 
"test.cxx", line 58:  Where: While instantiating "SignalHandler<5, 0>::SignalHandler(void(*)(int), int)". 
"test.cxx", line 58:  Where: Instantiated from non-template code. 

SunCC 5.14

$ /opt/developerstudio12.5/bin/CC test.cxx 
$ 

その問題が何であるか私には必ずしも明らかではありません。 Oracleのボードでも同様の問題がありますが、OPは基本的にRTFMに伝えられます:Sun Studio 11 "Warning (Anachronism)"

時代遅れの警告を解決するにはどうすればよいですか?


solaris:~$ cat test.cxx 
#include <signal.h> 

extern "C" { 
    typedef void (*SignalHandlerFn) (int); 
}; 

template <int S, bool O=false> 
struct SignalHandler 
{ 
    SignalHandler(SignalHandlerFn pfn = NULL, int flags = 0) : m_installed(false) 
    { 
    struct sigaction new_handler; 

    do 
    { 
     int ret = 0; 

     ret = sigaction (S, 0, &m_old); 
     if (ret != 0) break; // Failed 

     if (m_old.sa_handler != 0 && !O) break; 

     new_handler.sa_handler = (pfn ? pfn : &SignalHandler::NullHandler); 
     new_handler.sa_flags = (pfn ? flags : 0); 

     ret = sigemptyset (&new_handler.sa_mask); 
     if (ret != 0) break; // Failed 

     ret = sigaction (S, &new_handler, 0); 
     if (ret != 0) break; // Failed 

     m_installed = true; 

    } while(0); 
    } 

    ~SignalHandler() 
    { 
    if (m_installed) 
     sigaction (S, &m_old, 0); 
    } 

private: 
    struct sigaction m_old; 
    bool m_installed; 

    static void NullHandler(int /*unused*/) { /* continue*/ } 

private: 
    // Not copyable 
    SignalHandler(const SignalHandler &); 
    void operator=(const SignalHandler &); 
}; 

int main(int argc, char* argv[]) 
{ 
    SignalHandler<SIGTRAP, 0> handler; 
    return 0; 
} 
+0

NullHandlerの署名とは何ですか? – kfsone

+0

@kfsone - サンプルの下端。インライン定義は 'static void NullHandler(int/* unused * /){}'です。私は三項演算子もアンロールしました。問題は 'new_handler.sa_handler = pfn;'です。 – jww

+0

extern "C"である必要はありませんか? – kfsone

答えて

2

あなたは(のはSignalHandler_NullHandlerという名前を付けましょう)、通常のC関数にSignalHandler :: NullHandlerを変更することがあります。 その後、SignalHandler_NullHandlerとSignalHandlerFnの両方をextern "C"で囲みます。

BTW。これらの2つの関数を "整列"させる方法は私の推測でしたが、C/C++のキャスティングに問題があるというあなたのコメントのほうがはっきりと説明されています。式において

+0

@ M.M - * "標準C++では、Cスタイルのキャストはreinterpret_castと同じ効果を持つと定義されています..." - 興味深いのは、私は間違いなく別の動作を見ているからです(Cキャストは受け入れられ、C++キャストは受け付けません)。異なった行動はもう1つの質問を引き起こした。三項演算子の両側で 'reinterpret_cast'を使うときに問題を起こすバージョンは、SunCC 12.3と12.4です。 – jww

+0

私はキャストで間違ったパスをたどったので編集をロールバックしました。申し訳ありません。 – jww

1

pfn ? pfn : &SignalHandler::NullHandler 

第二及び第三のオペランドが異なるタイプを持っている(「C」言語の結合、および「C++」言語リンケージを持つ関数への1つのポイントを持つ関数への1つの点から) ;言語の連鎖を変える暗黙的な変換はありません。

このように表現が不適切です。別の答えは、キャストを使用することを示唆していますが、実行時の静的で未定義の動作を犠牲にして診断を抑制する可能性があります。異なるタイプの関数へのポインタを使用して関数を呼び出します。

もちろん、特定のコンパイラがC++標準で定義されていないシナリオでの動作を定義する拡張機能を提供する可能性があります。 (あるいは、 "とにかく"働く)。

SignalHandler::NullHandlerをC言語のリンケージを持つ関数に置き換えることをお勧めします。言語文法ではextern "C"がクラス定義の中に現れないので、クラスメンバーにすることはできません。

関連する問題