【问题标题】:Has anyone an example for wrapping a function in C++?有没有人用 C++ 包装函数的例子?
【发布时间】:2011-04-19 01:45:59
【问题描述】:

我在网上搜索了很多,但找不到适用于 g+ 的示例,所有示例都适用于 GCC。

我不断收到的错误是:

wrap_malloc.o: In function `__wrap_malloc(unsigned int)':
wrap_malloc.cc:(.text+0x20): undefined reference to `__real_malloc(unsigned int)'
wrap_malloc.o: In function `main':
wrap_malloc.cc:(.text+0x37): undefined reference to `__wrap_malloc'
collect2: ld returned 1 exit status

产生此错误的代码如下(如果我使用 GCC 编译它并将标头从 cstdio 更改为 stdio.h,则此代码有效):

#include <cstdio>
#include <cstdlib>

void *__real_malloc(size_t);

void *__wrap_malloc(size_t c) {
  printf("My malloc called with %d\n", c);
  return __real_malloc(c);
}

int main(void) {
  void *ptr = malloc(12);
  free(ptr);
  return 0;
}

我是这样编译的:

wrap_malloc.o: wrap_malloc.cc
    g++ -c wrap_malloc.cc -o wrap_malloc.o

wrap_malloc: wrap_malloc.o
    g++ wrap_malloc.o -o wrap_malloc -Wl,--wrap,malloc

【问题讨论】:

    标签: c++ linux gcc g++


    【解决方案1】:

    当您使用 C++ 编译器时,所有名称都会被破坏。当您运行 nm wrap_malloc.o 时,这意味着什么会变得很清楚,这应该会为您提供如下信息:

    00000000 b .bss
    00000000 d .data
    00000000 r .rdata
    00000000 t .text
             U __Z13__real_mallocj
    00000000 T __Z13__wrap_mallocj
             U _printf
    

    这意味着您使用 (U) 一个名为 __Z13__real_mallocj 的符号,并在文本段 (T) 中定义一个名为 __Z13__wrap_mallocj 的符号。但您可能需要一个名为__real_malloc 的符号。要实现这一点,您必须告诉编译器 __real_malloc 是 C 风格的函数,如下所示:

    extern "C" void *__real_malloc(size_t);
    
    extern "C" void *__wrap_malloc(size_t c) {
      printf("My malloc called with %d\n", c);
      return __real_malloc(c);
    }
    

    现在nm 的输出是:

    00000000 b .bss
    00000000 d .data
    00000000 r .rdata
    00000000 t .text
             U ___real_malloc
    00000000 T ___wrap_malloc
             U _printf
    

    您可以看到名称_printf 没有更改。这是因为在头文件中,很多函数已经声明为extern "C"。

    注意:我在 cygwin 环境中的 Windows 上完成了以上所有操作。这就是为什么在外部符号中有一个额外的前导下划线。

    【讨论】:

    • 非常感谢!现在我明白了这个问题。
    【解决方案2】:

    如果这是完整的代码,那么您遇到的问题是您还没有实现__real_malloc()!

    顺便说一句,带有双下划线的标识符是由语言保留的。您可能需要考虑选择不同的名称。

    【讨论】:

    • 这段代码是一个演示,我打算使用包装器进行测试。如果代码使用--wrap=malloc 编译,它会将所有调用重定向到_wrap_malloc。如果你想使用真实的东西你必须调用__real_malloc。这是文档 => 任何未定义的符号引用都将解析为“__wrap 符号”。任何对“_real 符号”的未定义引用都将被解析为符号。这可用于为系统函数提供包装器。包装函数应称为“_wrap 符号”。如果它想调用系统函数,它应该调用“_real符号”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 2015-06-17
    • 1970-01-01
    • 2020-06-15
    • 2012-02-22
    相关资源
    最近更新 更多