【问题标题】:glibc - force function call (no inline expansion)glibc - 强制函数调用(无内联扩展)
【发布时间】:2012-02-18 17:22:31
【问题描述】:

我有一个关于 glibc 函数调用的问题。是否有一个标志告诉 gcc 不要内联某个 glibc 函数,例如内存?

我已经尝试过 -fno-builtin-memcpy 和其他标志,但它们不起作用。目标是调用实际的 glibc memcpy 函数并且没有内联代码(因为编译时的 glibc 版本与运行时的不同)。它仅用于测试目的。通常我不会那样做。

有什么解决办法吗?

更新:

只是为了更清楚:过去 memcpy 即使在重叠区域也可以工作。这同时发生了变化,我可以在使用不同的 glibc 版本进行编译时看到这种变化。所以现在我想测试我的旧代码(在应该使用 memmove 的地方使用 memcpy)在具有较新 glibc(例如 2.14)的系统上是否正常工作。但要做到这一点,我必须确保调用新的 memcpy 并且没有内联代码。

最好的问候

【问题讨论】:

  • memcpy(params..)改写成(memcpy)(params..)
  • @osgx:这可以防止任何memcpy() 宏的扩展,但不会影响实际函数的内联。

标签: c gcc inline glibc


【解决方案1】:

这可能不是您想要的,但它似乎强制 gcc 生成对memcpy()间接调用:

#include <stdio.h>
#include <string.h>
#include <time.h>

// void *memcpy(void *dest, const void *src, size_t n)

unsigned int x = 0xdeadbeef;
unsigned int y;

int main(void) {
    void *(*memcpy_ptr)(void *, const void *, size_t) = memcpy;
    if (time(NULL) == 1) {
        memcpy_ptr = NULL;
    }
    memcpy_ptr(&y, &x, sizeof y);
    printf("y = 0x%x\n", y);
    return 0;
}

生成的程序集(gcc、Ubuntu、x86)包含一条call *%edx 指令。

如果没有 if (time(NULL) == 1) 测试(它永远不会成功,但编译器不知道),gcc -O3 足够聪明地认识到间接调用总是调用 memcpy(),然后可以将其替换为movl 指令。

请注意,编译器可以识别出如果memcpy_ptr == NULL 则行为未定义,并再次将间接调用替换为直接调用,然后再替换为movl 指令。带有-O3 的gcc 4.5.2 似乎并不那么聪明。如果gcc 是更高版本,您可以将memcpy_ptr = NULL 替换为与memcpy() 行为不同的某个实际函数的赋值。

【讨论】:

  • @user1169333:好的,想要的效果到底是什么?为什么间接调用不符合您的要求?
【解决方案2】:

理论上:

gcc -fno-inline -fno-builtin-inline ...

但是你说-fno-builtin-memcpy 并没有阻止编译器内联它,所以没有明显的理由可以更好地工作。

【讨论】:

  • 根据GCC manual-fno-inline适用于忽略源代码中的inline关键字。我相信所需的参数是-fno-inline-functions 结合-fno-builtin。我使用nm 进行检查,而不是检查汇编源代码中的中断调用。
  • 使用 -fno-inline-functions 和 -fno-builtin 二进制文件变得更小,因此标志会产生影响,但不会影响程序的结果(如我所料)。
【解决方案3】:
#undef memcpy
#define mempcy your_memcpy_replacement

在顶部的某个地方,但显然在#include 之后

并将 your_memcpy_replacement 标记为 属性((noinline))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    • 2013-06-04
    • 2012-01-12
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    相关资源
    最近更新 更多