1

I have a problem when using WEAK reference in C. Make assumption, I have the src code structure as follows:

//Eclipse C project structure

    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

And:

//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();
}

I got the result on the screen:

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

I can't use the REAL function anymore. All my making calls to the real test function is impossible because it was declared as __attribute__((weak)) before. So, Is there anybody having idea on this case ? The main purpose, I'd like to call my real test (in source_sample.c) but don't remove weak attribute as well.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
Thảo M. Hoàng
  • 1,224
  • 3
  • 20
  • 42
  • I've never used the `weak attribute` but you are putting it's declaration in a header file and include it in both source files that have `test()` defined. If anything, you should declare `__attribute__((weak))` in the source file. But then you call `test_function_weak` which resides in the same file as the 'weak' `test` function. Of course it would call that function (weak only means that the function is not seen globally). Last but not least, why do you `define static`? – CantrianBear Apr 13 '16 at 04:28
  • 2
    Standard C does not have function attributes; that's a GCC extension, supported also by certain other compilers. It would be well, therefore, for you to tag the question with the C implementation you are asking about. – John Bollinger Apr 13 '16 at 04:41
  • 1
    1) Why do you `#define static` instead of just not using `static` in the first place? – user253751 Apr 13 '16 at 04:49
  • 1
    Do not define keywords as macro names. It is very poor form, in part because it is likely to cause far more trouble than than is justified by any benefit it imparts. – John Bollinger Apr 13 '16 at 04:49
  • 2) That function ***is*** the "real" function. The other function doesn't exist. That's what weak linkage does. – user253751 Apr 13 '16 at 04:49
  • @CantrianBear, @immibis : Because `weak` reference must be public. So, I just ignore this keyword. – Thảo M. Hoàng Apr 13 '16 at 05:57

1 Answers1

2

First off, be aware that weak linkage is not a C concept. It is an ELF concept, at least for our purposes, and GCC (and other compiler) support for it is a C extension. Therefore, little of what I have to say is based on the C standard. With that said ...

Your program has two functions test(), both with weak linkage. If there were an alternative with strong linkage then that would override both. Since there is not, it is unspecified which of the two is linked to any given reference (call), but it follows from the mechanism of ELF dynamic linking that the same one would would be linked to every reference in any given dynamic object.

Other than system libraries, you have only one dynamic object in play -- the program -- so it stands to reason that the same implementation of test() is called at every point. It's unclear to me why you suppose it would be otherwise. Note in particular that the weird games you are playing with the static keyword are strictly obfuscatory. You have no actual static declarations anywhere in the code you present.

You indeed could declare a static function test in some file, and in that case you would expect calls to test() from within that file to be linked to the internal static version. To the best of my knowledge, however, a static function cannot also be weak. That wouldn't make any sense.

The main purpose, I'd like to call my real test (in source_sample.c) but don't remove weak attribute as well.

So you want to provide for overriding some references to the function but not others? Are you nuts? What a nightmare that would be to build, and I don't even want to think about maintaining it.

If you want to provide a default implementation that you can always call then you cannot make that the weak function. Doing so is inconsistent with always being able to call it. You can, however, make it a separate, ordinary function that the weak one calls, and any other function also can call:

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();
}

Anyone with access to test_default() can then call it, but whether it gets called as a result of calling test() depends on what version of test() is linked to the call -- it is weak, so a different version could be provided.

Note also that depending on the scope you want test_default() to have, it might be both possible and sensible to make it static, whereas test() must not be static as long as it is weak.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Thank you. In your above example, `test` is `weak` (as declared in `test.h`). So, if we define another version of `test` anywhere, we will never use `test` (defined in `test.c`) anymore because the program will re-route the call to _that other version of_ `test`. In the opposite, if there's no any other version of `test` is defined, `test` in **test.c** will be used. – Thảo M. Hoàng Apr 13 '16 at 06:14
  • @ThảoHoàngMinh, yes, you've got it, with one minor quibble: it is only if a **strongly-linked** alternative `test()` function is provided that you can rely on that version being called instead of the weakly-linked one provided. – John Bollinger Apr 13 '16 at 13:05