For some reason I get a segfault when calling a weak function but only if I put the weak definition in a static library. Here are my source files:
// mylib.h
#pragma once
void hello(const char* name) __attribute__((weak));
// mylib.cpp
#include "mylib.h"
#include <iostream>
void hello(const char* name) {
std::cout << "Hello " << name << "\n";
}
// main.cpp
#include "mylib.h"
int main() {
hello("world!");
}
Then I compile them:
$ g++ -o mylib.o -c mylib.cpp
$ g++ -o main.o -c main.cpp
Then if I link normally it works fine:
$ g++ -o main_works main.o mylib.o
$ ./main_works
Hello world!
However if I first put them in a static library, it segfaults!
$ ar rc mylib.a mylib.o
$ g++ -o main_fails main.o mylib.a
$ ./main_fails
Segmentation fault (core dumped)
What's going on here? The symbol table for mylib.o and mylib.a is identical (as you would expect) and has the weak symbol:
$ nm mylib.a
mylib.o:
...
0000000000000000 W _Z5helloPKc
...
However it is only resolved in main_works:
$ nm main_works | grep hello
000000000040076b W _Z5helloPKc
$ nm main_fails | grep hello
w _Z5helloPKc
I'm using GCC 8.5.0 on RHEL 8. I also tested GCC 13.2.1 and Clang 13.0.6 on Fedora 38 (though I guess it is really the linker that is screwing up here).
Edit: This fixes the segfault, but it doesn't explain why it segfaults in the first place. It also isn't a good solution because adding flags like this is difficult in most build systems.
g++ -o main_fails -Wl,--whole-archive main.o mylib.a -Wl,--no-whole-archive