1

C で WEAK 参照を使用するときに問題が発生します。次のような src コード構造があると仮定します。

//Eclipse C プロジェクトの構造

    drv
     |   dummy      
     |     |  dummy_Test.h
     |     |  dummy_TestWeakAttribute.h
     |   src
     |     |  source_sample.c
     |   test
     |     |  myModules
     |             strong_test_case.c
     |             weak_test_case.c
    test_program.c

と:

//test_program.c

#include "drv/dummy/dummy_TestWeakAttribute.h"
#include "drv/dummy/dummy_Test.h"

int main() {
    printf("===================\n");
    printf("  Welcome to main  \n");
    printf("===================\n");
                            // Expectation
    test();                 //-->real function
    function();             //-->real function
    test_function_strong(); //-->real function
    test_function_weak();   //-->weak function

    return 0;
}

//source_sample.c

#include "../dummy/dummy_TestWeakAttribute.h"
#include "../dummy/dummy_Test.h"

static void test(void) {
    printf("NOT overridden!\n");
}

static void function(void){

    int a =1;
    a++;
    test();
}

//dummy_Test.h

#ifndef DRV_DUMMY_DUMMY_TEST_H_
#define DRV_DUMMY_DUMMY_TEST_H_

#define static
//definitions

//struct definitions

//dummy functions

static void test(void);
static void function(void);

//global variable definitions

#endif /* DRV_DUMMY_DUMMY_TEST_H_ */

//dummy_TestWeakAttribute.h

#define static //disable static keyword

static void __attribute__((weak)) test(void);

//weak_test_case.c

#include "../../dummy/dummy_TestWeakAttribute.h"
#include "../../dummy/dummy_Test.h"

static void test(void){
    printf("overridden successfully!\n");
}

void test_function_weak(void){
    function();
}

//strong_test_case.c

#include "../../dummy/dummy_Test.h"

void test_function_strong(void){
    function();
}

画面に結果が表示されました:

===================
  Welcome to main  
===================
overridden successfully!
overridden successfully!
overridden successfully!
overridden successfully!

REAL関数が使えなくなりました。以前のように宣言されているため、実際の関数を呼び出すことはすべてtest不可能です__attribute__((weak))。それで、このケースについて考えている人はいますか?test主な目的は、私は本当の(in source_sample.c)を呼び出したいのですが、属性も削除しません。 weak

4

1 に答える 1

2

まず、弱いリンケージは C の概念ではないことに注意してください。これは、少なくとも私たちの目的では ELF の概念であり、GCC (およびその他のコンパイラ) のサポートは C 拡張です。したがって、私が言わなければならないことのほとんどは、C 標準に基づいています。とは言うものの ...

あなたのプログラムには 2 つの関数test()があり、どちらもリンクが弱いです。強力なリンケージを持つ代替手段があれば、それは両方をオーバーライドします。存在しないため、2 つのうちどちらが特定の参照 (呼び出し) にリンクされているかは特定されていませんが、ELF 動的リンクのメカニズムから、特定の動的オブジェクト内のすべての参照に同じリンクがリンクされることになります。

システム ライブラリを除いて、実行中の動的オブジェクトは 1 つだけ (プログラム) であるため、test()すべての時点で の同じ実装が呼び出されるのは理にかなっています。なぜそうでないと思うのか、私には不明です。特に、キーワードでプレイしている奇妙なゲームstaticは厳密に難読化されていることに注意してください。static提示するコードのどこにも実際の宣言はありません。

確かに、あるファイルでstatic関数testを宣言することができます。その場合、そのファイル内からの呼び出しが内部バージョンtest()にリンクされることが期待されます。staticしかし、私の知る限りでは、static関数が弱いということはあり得ません。それは意味がありません。

主な目的は、実際のテスト (source_sample.c 内) を呼び出したいのですが、weak 属性も削除しないことです。

関数へのいくつかの参照をオーバーライドし、他の参照はオーバーライドしないようにしますか? ばかじゃない?構築するのはなんて悪夢でしょう。私はそれを維持することさえ考えたくありません。

いつでも呼び出すことができるデフォルトの実装を提供したい場合は、それを弱い関数にすることはできません。そうすることは、常にそれを呼び出すことができるということと矛盾します。ただし、弱い関数が呼び出す別の通常の関数にすることができ、他の関数も呼び出すことができます。

test.h:

#ifndef TEST_H
#define TEST_H

void test(void) __attribute__((weak));
void test_default(void);

#endif

test.c:

#include "test.h"

void test_default(void) {
    printf("I am the default implementation");
}

void test(void) {
    test_default();
}

にアクセスできる人は誰でもtest_default()それを呼び出すことができますが、呼び出しの結果として呼び出されるかどうかは、呼び出しにリンクされている のtest()バージョンによって異なります。これは弱いため、別のバージョンが提供される可能性があります。test()

また、必要なスコープによってtest_default()は、それを作成することが可能であり、賢明である場合もありますstaticが、弱い限りtest()そうすべきではないことにも注意してください。static

于 2016-04-13T05:37:07.550 に答える