C++Builder社区版10.4中Boost.Multiprecision Win64编译出现链接错误的解决方案咨询
我之前帮同事处理过一模一样的问题,这个错误其实是C++Builder 10.4的Win64工具链缺失了对128位无符号整数运算的两个关键内置函数,而Boost.Multiprecision在处理大整数时刚好调用了它们。
问题根源
Boost.Multiprecision的cpp_int类型在进行某些运算(比如除法、取模)时,会生成依赖128位整数操作的代码。C++Builder的Win32环境通过兼容层间接支持了这些操作,但Win64版本的编译器/链接器并没有默认提供__udivti3(无符号128位除法)和__umodti3(无符号128位取模)这两个GCC风格的函数,所以链接时就会报未解析的外部符号错误。
三种可行的解决方案
1. 手动实现缺失的函数
最直接的办法是自己写这两个函数,让链接器找到对应的实现。新建一个.cpp文件(比如fix_udivti3.cpp),把下面的代码放进去,然后添加到项目中:
#include <cstdint> // 用extern "C"保证函数名不被C++名称修饰 extern "C" { // 计算 (high_dividend << 64 | low_dividend) / divisor uint64_t __udivti3(uint64_t high_dividend, uint64_t low_dividend, uint64_t divisor) { const __int128 dividend = static_cast<__int128>(high_dividend) << 64 | low_dividend; const __int128 divisor_128 = divisor; return static_cast<uint64_t>(dividend / divisor_128); } // 计算 (high_dividend << 64 | low_dividend) % divisor uint64_t __umodti3(uint64_t high_dividend, uint64_t low_dividend, uint64_t divisor) { const __int128 dividend = static_cast<__int128>(high_dividend) << 64 | low_dividend; const __int128 divisor_128 = divisor; return static_cast<uint64_t>(dividend % divisor_128); } }
这样链接器就能找到对应的符号,错误自然就消失了。这个方案不会影响性能,因为只是补全了缺失的底层函数。
2. 禁用Boost的128位整数优化
如果不想额外写代码,可以在包含Boost头文件之前定义一个宏,强制Boost.Multiprecision不使用128位整数的优化路径:
// 必须在包含Boost头文件之前定义这个宏 #define BOOST_MP_NO_128BIT_INTEGERS #include <boost/multiprecision/cpp_int.hpp> #include <boost/multiprecision/cpp_bin_float.hpp> #include <boost/rational.hpp> // 你的原有代码... using namespace std; using namespace boost::multiprecision; using boost::rational; typedef boost::rational<cpp_int> t_prob; int main (int argc, char *argv []) { t_prob a,b,c; a = 4; // a /= 6; b = 13; // b /= 7; c = a * b; std::cout << c << "\n"; }
这个方案的好处是简单,但可能会让大整数运算的性能稍微下降一点,不过对于大多数普通场景来说,这个影响几乎可以忽略。
3. 升级Boost版本(可选)
Boost 1.70是比较旧的版本了,后续的Boost版本(比如1.75及以上)针对C++Builder的Win64环境做了兼容性修复,可能已经内置了对这些函数的处理。如果你的项目没有依赖旧版本的特定功能,可以尝试升级到最新的稳定版Boost,说不定直接就能解决问题。
测试验证
按照上面任意一种方案修改后,重新编译Win64版本的项目,链接错误应该就能解决。比如用方案1的话,编译你的测试代码后,应该能正常输出52这个结果。
内容的提问来源于stack exchange,提问作者david

