【问题标题】:Automatically freeing memory on exit in a shared library在共享库中退出时自动释放内存
【发布时间】:2021-09-19 10:25:57
【问题描述】:

我的目标是用我自己的实现包装malloc(),然后使用LD_PRELOAD 技巧将该实现注入可执行文件以用于教育目的。

我创建了两个文件,test.c 用于测试注入,wrapper.c 包装了malloc() 并编译为共享库。

我的问题是这样的:

wrapper 是否有可能检测到它的调用者,test 已完成(在main() 的末尾)以释放它的内存 (dynamic_array)?

我无法将deinit() 之类的内容添加到wrapper,因为我不一定能像test 那样访问调用者的代码。

我知道在 C++ 中使用 RAII 可能是最好的,但是在 C 中可以做什么?

// test.c
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
    (void)malloc(1);
    return 0;
}

内置:

gcc -o test test.c
// wrapper.c
#define _GNU_SOURCE
#include <stdlib.h>
#include <dlfcn.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>

static void* (*real_malloc)(size_t size) = NULL;

// Untested pseudocode, but you get the idea
void *dynamic_array = NULL;
unsigned dynamic_array_idx = 0;
size_t dynamic_array_size = 100;

void add_ptr(void* ptr)
{
    if (!dynamic_array) {
        dynamic_array = real_malloc(dynamic_array_size );   
    }
    
    if (dynamic_array_idx >= dynamic_array_size) {
        dynamic_array_size *= 2;
        dynamic_array = realloc(dynamic_array, dynamic_array_size);
    }

    dynamic_array[dynamic_array_idx++] = ptr;
}

void* malloc(size_t size)
{
    if (real_malloc == NULL) {
        real_malloc = dlsym(RTLD_NEXT, "malloc");
    }
    
    void* ptr = real_malloc(size);
    add_ptr(ptr);
    return ptr;
}

内置:

gcc -c -fPIC -o wrapper.o wrapper.c
gcc -shared -o wrapper.so wrapper.o

跑了:

LD_PRELOAD=wrapper.so ./test

【问题讨论】:

  • 在应用程序结束时没有真正需要这样做。也可以使用atexit()注册销毁函数;
  • 使用 gcc,您可以访问与使用 __attribute__((destructor)) 调用 C++ 析构函数相同的机制。

标签: c unix


【解决方案1】:

real_malloc初始化时,可以使用atexit指定程序退出时调用的函数。你可以用它来清理你的内存。

另外,dynamic_array 应该具有类型 void ** 来存储 void * 的数组。

void cleanup(void)
{
    free(dynamic_array);
}

void* malloc(size_t size)
{
    if (real_malloc == NULL) {
        real_malloc = dlsym(RTLD_NEXT, "malloc");
        atexit(cleanup);   // register cleanup handler
    }
    
    void* ptr = real_malloc(size);
    add_ptr(ptr);
    return ptr;
}

【讨论】:

  • 我猜如果主程序dlcloses 库在退出之前会中断?
  • @NateEldredge 该库从不dlopen'ed,只是通过LD_PRELOAD 注入,所以应该不是问题。
猜你喜欢
  • 2013-01-18
  • 1970-01-01
  • 2015-01-25
  • 2012-05-03
  • 1970-01-01
  • 2013-07-13
  • 1970-01-01
  • 2022-01-12
  • 2021-07-26
相关资源
最近更新 更多