Skip to content

Instantly share code, notes, and snippets.

@mine260309
Last active February 11, 2019 04:52
Show Gist options
  • Save mine260309/3c1a1cba26af1847bc187e4ffae724d6 to your computer and use it in GitHub Desktop.
Save mine260309/3c1a1cba26af1847bc187e4ffae724d6 to your computer and use it in GitHub Desktop.
Demo of bug about init priority in both gcc and clang
#include "bar.h"
#include <memory>
template <typename T>
struct Constructor
{
Constructor(T&& fn)
{
fn();
}
Constructor() = delete;
~Constructor() = default;
};
void on_load();
// Putting this init before barGlobalPtr
static Constructor<void(*)(void)> init(on_load);
#ifdef BUG
std::unique_ptr<bar> barGlobalPtr(new bar(1));
#else
std::unique_ptr<bar> barGlobalPtr
__attribute__((init_priority(101))) (new bar(1));
#endif
//void on_load() __attribute__((constructor));
void on_load()
{
barGlobalPtr.reset(new bar(2));
}
void bar_func(void)
{
printf("bar global ptr %p, value: %d\n", barGlobalPtr.get(), barGlobalPtr->m);
}
#pragma once
#include <cstdio>
struct bar
{
bar(int i)
:m(i)
{
printf("%s: %p, %d\n", __func__, this, m);
}
~bar()
{
printf("%s: %p, %d\n", __func__, this, m);
}
int m;
};
extern "C" void bar_func(void);
#include "bar.h"
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <dlfcn.h>
using bar_func_type = void(*)(void);
int main(void)
{
auto h = dlopen("./libbar.so", RTLD_LAZY);
if (!h)
{
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
bar_func_type f = nullptr;
auto r = dlsym(h, "bar_func");
if (!r)
{
fprintf(stderr, "%s\n", dlerror());
goto out;
}
*reinterpret_cast<void**>(&f) = r;
f();
out:
dlclose(h);
return 0;
}
CC=g++
#CC=clang++
CFLAGS=-c -Wall -fpic
BUGFLAG=-DBUG
SOURCES=main.cpp bar.cpp
all: main
main: main.o libbar.so
$(CC) -o main main.o -ldl
libbar.so: bar.cpp
$(CC) $(BUGFLAG) -shared -fPIC -o $@ $<
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
clean:
@rm -f main main.o bar.o libbar.so
###
#
# To show the bug:
#
# make
# ./main
#
# Output:
#
# bar: 0x55e42b836570, 2
# bar: 0x55e42b8369a0, 1
# bar global ptr 0x55e42b8369a0, value: 1
# ~bar: 0x55e42b8369a0, 1
#
# To show the fix of the bug:
#
# make BUGFLAG=
# ./main
#
# Output:
#
# bar: 0x5592bb9df570, 1
# bar: 0x5592bb9df9a0, 2
# ~bar: 0x5592bb9df570, 1
# bar global ptr 0x5592bb9df9a0, value: 2
# ~bar: 0x5592bb9df9a0, 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment