📜  C中的函数插入,以及用户定义的malloc()的示例

📅  最后修改于: 2021-05-30 08:21:53             🧑  作者: Mango

函数插入是将对动态库中函数的调用替换为对用户定义的包装器的调用的概念。

有什么应用?

  1. 我们可以计算对函数的调用次数。
  2. 存储调用者的信息和传递给函数的参数以跟踪使用情况。
  3. 检测内存泄漏,我们可以覆盖malloc()并跟踪分配的空间。
  4. 我们可以添加自己的安全策略。例如,我们可以添加一个策略,即不能以超过指定的递归深度的方式调用fork。

如何进行函数设置?
任务是编写我们自己的malloc()并确保在库malloc()的位置调用了我们自己的malloc()。下面是一个驱动程序,用于测试malloc()的不同类型的插入。

// File Name : hello.c
  
#include 
#include 
#include 
  
int main(void)
{
    // Call to user defined malloc
    void *ptr = malloc(4);
      
    printf("Hello World\n");
    return 0;
}
  1. 编译时间:编译源代码时,用我们自己的函数替换库调用。
    /* Compile-time interposition of malloc using C preprocessor. 
       A local malloc.h file defines malloc as wrapper */
      
    // A file that contains our own malloc function
    // File Name : mymalloc.c
    #include 
    #include 
    void *mymalloc(size_t s)
    {
       printf("My malloc called");
       return NULL;
    }
    
    // filename : malloc.h
    // To replace all calls to malloc with mymalloc
    #define malloc(size) mymalloc(size)
    void *mymalloc(size_t size);
    

    在Linux上执行上述步骤:

    // Compile the file containing user defined malloc()
    :~$ gcc  -c mymalloc.c
    
    // Compile hello.c with output file name as helloc. 
    // -I. is used to include current folder (.) for header
    // files to make sure our malloc.h is becomes available.
    :~$ gcc  -I. -o helloc hello.c mymalloc.o
    
    // Run the generated executable
    :~$ ./helloc
    My malloc called
    Hello World 

  2. 链接时间:将可重定位目标文件静态链接以形成可执行目标文件时。
    // filename : mymalloc.c
    /* Link-time interposition of malloc using the
       static linker’s (ld) "--wrap symbol" flag. */
    #include 
      
    // __real_malloc() is used to called actual library
    // malloc()
    void *__real_malloc(size_t size);
      
    // User defined wrapper for malloc()
    void *__wrap_malloc(size_t size)
    {
       printf("My malloc called");
       return NULL;
    }
    

    在Linux上执行上述步骤:

    // Compile the file containing user defined malloc()
    :~$ gcc  -c mymalloc.c
    
    // Compile hello.c with output name as hellol  
    // "-Wl,--wrap=malloc" is used tell the linker to use
    //  malloc() to call __wrap_malloc(). And to use 
    // __real_malloc() to actual library malloc() 
    :~$ gcc  -Wl,--wrap=malloc -o hellol hello.c mymalloc.o
    
    // Run the generated executable
    :~$ ./hellol
    My malloc called
    Hello World 

  3. 加载/运行时间:将可执行对象文件加载到内存中,进行动态链接,然后执行。

    环境变量LD_PRELOAD为加载程序提供了要在命令或可执行文件之前加载的库列表。
    我们创建一个动态库,并确保在我们的hello.c可执行文件之前加载了它。

    /* Run-time interposition of malloc based on dynamic linker’s
       (ld-linux.so) LD_PRELOAD mechanism */
    #define _GNU_SOURCE
    #include 
      
    void *malloc(size_t s)
    {
       printf("My malloc called\n");
       return NULL;
    }
    

    在Linux上执行上述步骤:

    // Compile hello.c with output name as helloc
    :~$ gcc -o hellor hello.c
    
    // Generate a shared library myalloc.so. Refer
    // https://www.geeksforgeeks.org/working-with-shared-libraries-set-2/
    // for details.
    :~$ gcc -shared -fPIC -o mymalloc.so mymalloc.c
    
    // Make sure shared library is loaded and run before .
    :~$ LD_PRELOAD=./mymalloc.so ./hellor
    My malloc called
    Hello World
    

    用户定义的malloc的代码应较小,以提高可读性。理想情况下,它应该通过调用库malloc()来分配内存。

    来源:
    https://www.utdallas.edu/~zxl111930/spring2012/public/lec18-handout.pdf

    要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”