2016-12-01 95 views
1

我打算實現自己的malloc /免費的,我遇到了一些問題,而試圖以我的共享庫與我的可執行鏈接。覆蓋libc的功能,而不LD_PRELOAD

現在,我可以得到它通過鏈接。所以可執行與LD_PRELOAD工作,但不是,雖然我能得到similiar的庫,例如tcmalloc,通過它們鏈接到我的可執行正常只是工作,並會喜歡做同樣的事情。

我建立通過CMake的一切,這是我的共享庫的CMakeLists:

cmake_minimum_required(VERSION 2.8) 
project(allocator) 

add_library(allocator SHARED exports.cpp) 
target_link_libraries(allocator dl) 

target_compile_features(allocator PRIVATE cxx_range_for) 

,這是exports.cpp:

#ifndef _GNU_SOURCE 
#define _GNU_SOURCE 
#endif 

#include <stdio.h> 
#include <dlfcn.h> 

typedef void * (*MallocType)(size_t); 
typedef void (*FreeType)(void *); 

static bool g_initialized = false; 

static MallocType real_malloc = nullptr; 
static FreeType real_free = nullptr; 

static void alloc_init(void) 
{ 
    real_malloc = (MallocType) dlsym(RTLD_NEXT, "malloc"); 

    if (!real_malloc) 
    { 
     fprintf(stderr, "Error in `dlsym`: %s\n", dlerror()); 
    } 

    real_free = (FreeType) dlsym(RTLD_NEXT, "free"); 

    if (!real_free) 
    { 
     fprintf(stderr, "Error in `dlsym`: %s\n", dlerror()); 
    } 

    g_initialized = true; 
} 

extern "C" void * malloc(size_t size) 
{ 
    if (!g_initialized) 
    { 
     alloc_init(); 
    } 

    printf("Allocate %u.\n", size); 
    return real_malloc(size); 
} 

extern "C" void free(void *ptr) 
{ 
    if (!g_initialized) 
    { 
     alloc_init(); 
    } 

    printf("Free %p.\n", ptr); 
    real_free(ptr); 
} 

正如我所說的,要連結的導致.so到一個可執行文件並不真正鏈接庫(在ldd中沒有條目,並且調用libc malloc)。我想知道我做錯了什麼。

編輯: 我也試圖與

g++ -o liballocator.so -shared exports.cpp -std=c++11 -fPIC -ldl 
g++ -o test launcher.cpp memusage.cpp app.cpp -ldl -L. -lallocator -std=c++11 
+1

這顯然不是C,而是用C++編譯器編譯的。將C編譯爲C,並使用相應的頭文件與您的C++代碼鏈接。標準庫的名稱是保留的。使用它們(至少在這裏你會這樣做)調用未定義的行爲。 – Olaf

+0

啓用make的詳細輸出並檢查實際執行的鏈接命令可能很明顯。 –

+0

我嘗試編譯純C,但結果是相同的,我也會假設我應該能夠鏈接C++代碼,特別是因爲LD_PRELOAD實際工作。 – tuccio

回答

1

CMake的編譯是不是你在這裏選擇的工具。 CMake爲C源創建makefile或IDE項目文件,並且有一種工作假設,即所有代碼都以傳統方式進行傳統操作。如果你已經承諾提供你自己的malloc,那不再是真的。

大多數C編譯器可以被鏈接到用戶提供的malloc版本的鏈接,通常通過玩鏈接標誌的順序。但這是一個容易出錯的過程,因爲可能會有間接調用或子模塊過早綁定。您可以通過重命名malloc()mymalloc()來立即解決所有這些問題,但當然您必須重寫客戶端代碼。

+0

這看起來更像是評論而不是答案。 – Olaf

+0

C++也是如此:它不是解決方案的一部分,它是問題的一部分。 –