0

(環境:gcc 4.6、c ++ 11、glibc 2.13、binutils 2.21)

背景については、次の「リンク」デモを検討してください。

foo.h

#pragma once
#include <iostream>

void foo();

foo1.cpp

#include "foo.h"

void foo()
{
    std::cout << "foo1";
}

foo2.cpp

#include "foo.h"

void foo()
{
    std::cout << "foo2";
}

main.cpp

#include "foo.h"

int main()
{
    foo();
}

Makefile

compile: main.o foo1.o foo2.o

case1: compile
    g++ -o case1.x main.o

case2: compile
    g++ -o case2.x main.o foo1.cpp

case3: compile
    g++ -o case3.x main.o foo1.o foo2.o

clean:
    rm *.o *.x

次のような関数宣言があります。

void foo();

そして、それの複数の定義があります。1つはfoo1.cppにあり、もう1つはfoo2.cppにあります。

.cppファイルを.oファイルにコンパイルします。

$ make compile

問題ありません。main.o、foo1.o、foo2.oが生成されます。

ケース1

次に、main.oだけをリンクしてみます。

$ make case1
error: undefined reference to 'foo()'

わかりました。main.oはfooを参照していますが、定義がリンクされていません。

ケース2

次に、main.oとfoo1.oをリンクしてみます

$ make case2

foo1.oにはfooの単一の定義があるため、エラーなしでリンクします。

ケース3

次に、main.ofoo1.oとfoo2.oをリンクしてみます

$ make case3
error: multiple definition of 'foo()'

リンカは、foo1.oとfoo2.oでfooの2つの定義を検出するため、ランダムな定義を取得するのではなく、エラーで高速に失敗し、リンクしません。

質問

私の質問は次のとおりです。

  1. foo1.cppのバージョンのfoo(おそらく何らかのgcc属性またはプラグマを使用)の定義を「弱い」とマークすることは可能ですか?具体的には、ケース1とケース2の動作を同じままにし、ケース3の動作を変更して警告やエラーなしで正常にリンクし、foo2.cppのfooの定義をリンクする(「弱い」定義をオーバーライドする)ことを意味します。 foo1.cppで)。

  2. 実行時にfooの弱いバージョンがリンクされているか(関数を明らかに実行せずに)強いバージョンがリンクされているかをテスト(およびブール変数に割り当てる)することは可能ですか?つまり、次のようにmainで関数を実装します。

    template<typename FunctionPtr>
    bool is_weak_linked(FunctionPtr fp);
    

is_weak_linked(foo)は、ケース2ではtrueを返し、ケース3ではfalseを返す必要があります。

4

1 に答える 1

1

#1へ:

void foo() __attribute__((weak));
void foo()
{
    ...
}

#2へ:私はそうは思わない、あなたがしている静的リンクではない。その情報はリンク時に失われます。

編集

あなたはいつでも#2の周りにあなたの方法を抽象化することができます。いくつかの例:

// Foo.h
extern void foo();
extern "C" void default_foo();
extern const bool is_weak_foo_linked;
template <void (*)()> bool is_weak_linked();

// Foo1.cc
extern "C" void default_foo() {...}
void foo() __attribute__((weak, alias("default_foo")));

extern const bool __attribute__((weak)) is_weak_foo_linked=true;
template <> bool is_weak_linked<foo>() __attribute__((weak));
template <> bool is_weak_linked<foo>() {return true;}

// Foo2.cc
void foo() {...}
extern const bool is_weak_foo_linked=false;
template <> bool is_weak_linked<foo>() {return false;}

// main.cc
#include "foo.h"
#include <iostream>
int main() {
    foo();
    std::cout<<is_weak_foo_linked<<std::endl;
    std::cout<<is_weak_linked<foo>()<<std::endl;
    std::cout<<(foo==default_foo)<<std::endl;
}
于 2012-02-01T23:30:47.163 に答える