New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to compile with -static #442
Comments
I get the same error:
|
same issue using default jemalloc options:
then using libjemalloc.a that I just built:
Does this work for you? |
Drop the -static (don't worry, this is still including static versions of your libs, just not the system libs). This is my preferred approach:
|
Thanks the -Ofast trick works. I'm building a golang binary that includes jemalloc and would like it to be completely static (as most golang binaries are). Can you shed some light onto as to why -Ofast get around this error? Also why is the behavior different between tcmalloc and jemalloc in this regard? I appreciate all your help! |
@kspinka also it looks like with -Ofast none of the jemalloc symbols make it into the binary:
|
Ok, that's not the right thing to do. Forget you even saw that dirty -Ofast trick. I really don't think it's wise to statically link libc and libpthread, as they may vary in their implementations across distros and versions (Linux I assume?). So all that being said, the right way to do what you want to do, if you insist on this totally static situation, is to enable the jemalloc prefix; compile with: And then either use the je_malloc() type functions directly, or use glibc's malloc hooks to intercept your malloc calls: http://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html Here's an example I found (credit to Greg Dhuse): #include <stdlib.h>
#include <jemalloc/jemalloc.h>
/* Prototypes for __malloc_hook, __free_hook */
#include <malloc.h>
/* Prototypes for our hooks. */
static void my_init_hook (void);
static void *my_malloc_hook (size_t, const void *);
static void my_free_hook (void*, const void *);
/* Override initializing hook from the C library. */
void (*__malloc_initialize_hook) (void) = my_init_hook;
static void
my_init_hook (void)
{
__malloc_hook = my_malloc_hook;
__free_hook = my_free_hook;
}
static void *
my_malloc_hook (size_t size, const void *caller)
{
return je_malloc(size);
}
static void
my_free_hook (void *ptr, const void *caller)
{
je_free(ptr);
}
int main()
{
je_malloc_stats_print(NULL, NULL, NULL);
void *foo = malloc(123);
je_malloc_stats_print(NULL, NULL, NULL);
free(foo);
return 0;
} |
thanks I'll try this out. Does tcmalloc include similar hooks? I'm curious as to why it works with tcmalloc without any changes. |
I'm pretty sure they (tcmalloc) take advantage of the aliasing system in gcc to override the "weakly" defined symbols in libc with their own "strongly" defined ones. This way the linker, when seeing both, will prefer the strong ones and ignore the weak ones. ...
#define ALIAS(tc_fn) __attribute__ ((alias (#tc_fn), used))
...
extern "C" {
void* malloc(size_t size) __THROW ALIAS(tc_malloc);
void free(void* ptr) __THROW ALIAS(tc_free);
void* realloc(void* ptr, size_t size) __THROW ALIAS(tc_realloc);
void* calloc(size_t n, size_t size) __THROW ALIAS(tc_calloc);
void cfree(void* ptr) __THROW ALIAS(tc_cfree);
void* memalign(size_t align, size_t s) __THROW ALIAS(tc_memalign);
void* valloc(size_t size) __THROW ALIAS(tc_valloc);
void* pvalloc(size_t size) __THROW ALIAS(tc_pvalloc);
int posix_memalign(void** r, size_t a, size_t s) __THROW
ALIAS(tc_posix_memalign);
#ifndef __UCLIBC__
void malloc_stats(void) __THROW ALIAS(tc_malloc_stats);
#endif
int mallopt(int cmd, int value) __THROW ALIAS(tc_mallopt);
#ifdef HAVE_STRUCT_MALLINFO
struct mallinfo mallinfo(void) __THROW ALIAS(tc_mallinfo);
#endif
size_t malloc_size(void* p) __THROW ALIAS(tc_malloc_size);
#if defined(__ANDROID__)
size_t malloc_usable_size(const void* p) __THROW
ALIAS(tc_malloc_size);
#else
size_t malloc_usable_size(void* p) __THROW ALIAS(tc_malloc_size);
#endif
} // extern "C" I'm not sure why jemalloc doesn't use this. It's a good question. |
Using |
problematic when statically linking cf. jemalloc/jemalloc#442
problematic when statically linking cf. jemalloc/jemalloc#442
It turns out to not be a weak symbol issue, at least since ~2006 https://sourceware.org/bugzilla/show_bug.cgi?id=2765 Implementing all the __libc * symbols, like tcmalloc, allows the linker to drop all of glibc's malloc.o, and statically link correctly. Patch attached |
glibc defines its malloc implementation with several weak and strong symbols: strong_alias (__libc_calloc, __calloc) weak_alias (__libc_calloc, calloc) strong_alias (__libc_free, __cfree) weak_alias (__libc_free, cfree) strong_alias (__libc_free, __free) strong_alias (__libc_free, free) strong_alias (__libc_malloc, __malloc) strong_alias (__libc_malloc, malloc) The issue is not with the weak symbols, but that other parts of glibc depend on __libc_malloc explicitly. Defining them in terms of jemalloc API's allows the linker to drop glibc's malloc.o completely from the link, and static linking no longer results in symbol collisions. Another wrinkle: jemalloc during initialization calls sysconf to get the number of CPU's. GLIBC allocates for the first time before setting up isspace (and other related) tables, which are used by sysconf. Instead, use the pthread API to get the number of CPUs with GLIBC, which seems to work. This resolves #442.
@djwatson and @jasone thanks for the fix. I can verify it works. However, if a program calls fork there is one more reference to libc's malloc.o that would need to be implemented for the linker to drop malloc.o. Here's a simple repro
and if you look at test.map produced by the linker:
|
@bassam, I can see how this is probably an issue for jemalloc, but I'm confused by the repro output you provided being specific to tcmalloc rather than jemalloc. Is there any significance to this? |
@jasone sorry cut&paste issue fixed. FWIW, the same issue exists with tcmalloc. |
Cool, thanks for the clarification. |
I think the fork issue is caused by a glibc bug which was fixed in glibc 2.25. |
It does look like its fixed in 2.25, however, thats still in development and might take a long time to be available on popular distros. I wonder if it would be useful to patch this on the jemalloc side, something like:
|
FWIW, I found a simple workaround https://github.com/rook/rook/blob/master/pkg/cephmgr/cephd/malloc.go. Feel free to close this if you'd like. It really is a glibc issue. |
Okay, closing. Thank you for following up! |
I'm unable to compile a simple static program with jemalloc. I'm using the jemalloc-dev package on Ubuntu and I've not compiled it from source. Here's a very simple repro:
When I compile this I get the following:
FWIW, when using tcmalloc it compiles fine:
Do I need to build jemalloc with different options to enable this?
The text was updated successfully, but these errors were encountered: