C ++ compilations and references with undefined function pointer

This code:

void undefined_fcn();
void defined_fcn() {}

struct api_t {
    void (*first)();
    void (*second)();
};
api_t api = {undefined_fcn, defined_fcn};

      

defines a global variable api

with a pointer to a non-existent function. However, it compiles and, to my surprise, links with absolutely no complaints from GCC, even with all those flags -Wall -Wextra -Werror -pedantic

.

This code is part of the shared library. It is only when I load the library that it finally fails at runtime. How can I check for the library link time that I haven't forgotten to define any function?


Update: this question refers to the same problem, and the answer is the same: -Wl,--no-undefined

. (by the way, I think it could even be labeled as a duplicate). However, as per the accepted answer below, you have to be careful when using -Wl,--no-undefined

.

+3


source to share


2 answers


This code is part of the shared library.

This is the key. The whole purpose of having a shared library is to have an "incomplete" shared object with undefined symbols that should be resolved when loading the main executable and all other shared libraries it is linked to. At that time, the runtime loader tries to resolve all undefined characters; and all undefined characters must be allowed, otherwise the executable will not run.

You stated that you are gcc

, so you are probably using GNU ld

. For the above reason ld

will link the shared library with undefined symbols, but fail to link the executable unless all undefined symbols are resolved against the shared libraries that the executable linked to. Thus, the expected behavior at runtime is that the runtime loader is expected to resolve all characters successfully as well; therefore, the only situation where the runtime loader does not launch the executable will indicate a fatal runtime error (for example, replacing a shared library with an incompatible version).



There are several options you can use to override this behavior. The parameter --no-undefined

specifies ld

to report link failure for undefined symbols when linking shared libraries like executables. When called ld

indirectly through gcc

this becomes -Wl,--no-undefined

.

However, you will most likely find it to be a lost offer. You better hope that none of the code in your shared library uses any class in the C ++ or C standard library. Because, guess what? - these links will be undefined symbols and you won't be able to link your shared library!

In other words, it is a necessary evil that you need to deal with.

+3


source


You cannot tell the compiler if you forgot to define a function in this implementation file. And the reason is that when you define a function, it is implicitly tagged extern

in C ++. And you can't tell what's in the shared library until after linking it (the compiler linker doesn't know if the link has been set)

If you are not familiar with what it means extern

. Things marked extern

with an external link signal, so if you have a variable that extern

, the compiler does not require a definition for that variable to be in the translation block that uses it. The definition can be in another implementation file, and the link is resolved at link time (when you link to the translation unit that defines the variable). The same goes for functions, which are essentially function type variables.



To get the behavior static

you want , make a function that tells the compiler that the function is not extern

and is part of the current translation unit, in which case it must be defined -Wundefined-internal

that ( -Wundefined-internal

is part -Werror

, so just compile with that)

+3


source







All Articles