rand()函数的动态链接器错误

时间:2016-02-11 02:54:57

标签: c++ linux c++11 dynamic-linking

我之前已经提出了一个问题,但再次参考了以下代码

#include <iostream>
using std::cout;
using std::endl;
#include <dlfcn.h>

int rand() throw() {

    // get the original rand() function
    static auto original_rand = (decltype(&rand)) dlsym(RTLD_NEXT, "rand");

    cout << "Call made to rand()" << endl;
    return original_rand();
}

为什么在以下错误中编译此结果

error: exception specification in declaration does not match previous declaration

为什么会这样?链接器如何知道这只是我自己声明的另一个rand()函数,而是现有版本的rand()

1 个答案:

答案 0 :(得分:3)

您的一个标头文件(我的情况为<iostream>)默默地包含<stdlib.h>,其中包含rand()功能。后者没有任何异常规范。在您的代码中,您尝试重载rand(),但签名与<stdlib.h>中的签名相同,但异常说明符(不属于函数类型,因此不能单独重载),因此,您得到编译时错误(不是链接器错误,正如您在问题中提到的那样)。

如果你想知道为什么静态包含的函数rand()在全局命名空间中也是可见的(不像你期望的那样只能看作std::rand),那是因为C库函数经常导入到标准C ++头文件通过直接

// <new_cpp_header>
#include <old_c_header.h> 

接着是

namespace std
{
    using old_function_from_old_c_header;
} 

因此该函数在全局命名空间和namespace std;中都会结束。这不是一个非常好的做法IMO,但现在大多数编译器都是这样做的。

例如,<cstdio>文件包含:

// <cstdio>
#include <stdio.h>
namespace std
{
    using printf;
    // ...
}

因此printfstd::printf都可见,即使您只包含<cstdio>(而非<stdio.h>)。