有没有办法替换库中的函数?

时间:2010-11-23 14:09:18

标签: c++ linux g++

我使用一个库来定义脚本语言的内部除法运算符。不幸的是,它不会对除数进行零检查。这导致了很多令人头疼的问题。我知道运营商的签名。

double ScriptClass::Divide(double&, double&);

可悲的是,它甚至不是C函数。有什么方法可以让我的应用程序使用我自己的Divide函数而不是ScriptClass::Divide函数吗?

编辑:      我知道dlopen(NULL,..)并用用户定义的函数替换“C”函数。这可以为类成员函数完成(不使用错位名称)吗?

5 个答案:

答案 0 :(得分:3)

答案 1 :(得分:3)

一般来说,这取决于程序员,而不是基础除法运算符,以防止除零。如果你将零除以很多,这似乎表明所使用的算法存在可能的缺陷。考虑重新编写算法,或者如果这不是一个选项,则保护调用除以零检查。您甚至可以在protected_divide类型函数中执行此操作。

所有这一切,假设因为它看起来像一个C ++函数,你有一个C ++库编译了你用来构建你的应用程序的所有相同的选项,所以名称修改匹配你可能能够将函数重新定义为.so并使用LD_PRELOAD强制加载。如果您静态链接,我认为您可以在自己的.o文件中创建该函数,并在库本身之前链接该文件将导致链接器获取您的版本。

答案 2 :(得分:1)

正如其他人所提到的,各种链接器和动态链接器实现将提供看起来像这样的解决方案。

但是,如果您使用任何这些功能(GNU ld的--wrap,ld.so的LD_PRELOAD等)重新定义一个C ++函数,您违反了单一定义规则,因此调用未定义的行为。

在编译库时,允许编译器以其认为合适的任何方式内联所讨论的函数,这意味着在所有情况下都可能不会调用函数的重新定义。

请考虑以下代码:

class A
{
public:
    void foo();
    void bar();
};

void A::foo()
{
    std::cout << "Old version.\n";
}

void A::bar()
{
   foo();
}

GCC 4.5,当使用-O3调用时,实际上会决定将foo()的定义内联到bar()中。如果你以某种方式让你的链接器用你自己的定义替换A :: foo()的这个定义,A :: bar()将输出字符串“Old version。\ n”。< / p>

所以,总而言之:不要。

答案 3 :(得分:0)

我没有想到,但是你可以使用ld的--wrap选项让特定的函数根据其旧名称给出一个新名称。然后,您可以编写它的新版本,如果愿意,也可以转发到旧版本。

此处快速概述:

http://linux.die.net/man/1/ld

我过去曾使用它来挂钩malloc(等),而不必重新编译运行时库,虽然这不是在Linux上(它是一个没有运行时加载的嵌入式事物)。我没有使用它来包装C ++函数,但是如果你能以某种方式处理C ++调用约定,并且你可以使用原始函数的错位名称创建一个函数,并让编译器接受对某个丑陋函数的调用用它中有趣的字符命名...我不明白为什么它不可能使其成功。

答案 4 :(得分:0)

短暂Q, 你不能用自己的代码包装课程吗? 一开始会有些头痛,但之后你可以简化很多功能。

(或者甚至只用宏包裹函数)