rand() 函数的动态链接器错误
dynamic linker error with rand() function
我之前已经问过这方面的问题,但再次参考以下代码
#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()
的现有版本?
您的一个头文件(在我的例子中是 <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;
中。在我看来,这不是一个很好的做法,但现在大多数编译器都是这样做的。
例如,<cstdio>
文件有:
// <cstdio>
#include <stdio.h>
namespace std
{
using printf;
// ...
}
所以 printf
和 std::printf
都可见,即使您只包含 <cstdio>
(而不是 <stdio.h>
)。
我之前已经问过这方面的问题,但再次参考以下代码
#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()
的现有版本?
您的一个头文件(在我的例子中是 <iostream>
)默默地包含 <stdlib.h>
,其中包含 rand()
函数。后者没有任何异常规范。在您的代码中,您尝试重载 rand()
,但签名与 <stdlib.h>
中的签名相同,除了异常说明符(它不是函数类型的一部分,因此不能单独重载),因此你会得到一个编译时错误(不是链接器错误,正如你在问题中提到的那样)。
如果您想知道为什么静默包含的函数 rand()
在全局命名空间中也是可见的(不像您预期的那样仅作为 std::rand
可见),那是因为通常导入 C 库函数通过直接
// <new_cpp_header>
#include <old_c_header.h>
其次是
namespace std
{
using old_function_from_old_c_header;
}
所以该函数最终出现在全局命名空间和 namespace std;
中。在我看来,这不是一个很好的做法,但现在大多数编译器都是这样做的。
例如,<cstdio>
文件有:
// <cstdio>
#include <stdio.h>
namespace std
{
using printf;
// ...
}
所以 printf
和 std::printf
都可见,即使您只包含 <cstdio>
(而不是 <stdio.h>
)。