在 C++ 中发现 glibc 版本的问题

Problems discovering glibc version in C++

我的应用程序分发了两个二进制文件。一个链接到旧的 glibc(例如 2.17),另一个二进制文件以更新的 glibc(例如 2.34)为目标。我还分发了一个启动器二进制文件(链接到 glibc 2.17),它询问用户的 libc 版本,然后 运行s 正确的二进制文件。

我建立用户 libc 的代码如下所示:

std::string gnu(gnu_get_libc_version());
double g_ver = std::stod(gnu);
if(g_ver >= 2.34)
{
     return GLIBC_MAIN;
}
else
{
     return GLIBC_COMPAT;
}

这对于最好的部分来说是完美的,但是,我的一些用户报告说尽管有一个新的 glibc,旧的 glibc 二进制文件实际上是 运行。我对此进行了调查,发现 double g_ver 等于 2,而不是应有的 2.34。也就是说,小数部分丢失了。 gnu_get_libc_version() 始终具有正确的值,因此在将字符串转换为双精度值时一定是个问题。

我也试过boost::lexical_cast但是这个效果是一样的

std::string gnu(gnu_get_libc_version());
//double g_ver = std::stod(gnu);
double glibc = boost::lexical_cast<double>(gnu);
if(g_ver >= 2.34)
{
  return GLIBC_MAIN;
}
else
{
   return GLIBC_COMPAT;
}

不用说,即使 运行 与受影响的用户使用完全相同的 Linux 发行版/版本,我也无法在我的任何计算机上重现此行为。

有人知道为什么 boost::lexical_cast 或 std::stod 有时会漏掉版本号的小数部分吗?有替代方法吗?

更新

经进一步测试,使用不同的语言环境时会引入此问题。我在测试机器上将语言环境设置为 fr_FR.UTF-8 并且能够重现此问题。但是,gnu_get_libc_version() 的输出似乎是正确的,但 std::stod 无法解析版本的小数点部分。

有人知道如何解决这个问题吗?

这可能是用户的语言环境吗? 小数点分隔符不是“.”在所有语言环境中,stod 使用当前语言环境?

gnu_get_libc_version() 可能 return 不仅仅是 X.X,例如可能是 2.0.1。

但是 strtod 不会处理数字的所有无效部分,在这种情况下等于 2.0。

您需要将实际值验证为字符串 return 从 gnu_get_libc_version 编辑到您当前无法访问的版本

根本问题是 glibc 版本是字符串而不是十进制数。因此,对于“正确”的解决方案,您需要手动解析它并实现您自己的逻辑来决定哪个版本更大或更小。

但是,作为一种快速而肮脏的破解方法,请尝试插入行

setlocale(LC_NUMERIC, "C");

strtod 调用之前。这会将数字语言环境设置回默认的 C 语言环境,其中小数分隔符为 .。如果您稍后在程序中执行某些需要正确语言环境的操作,则需要将其重新设置。根据你的程序如何初始化语言环境,比如

setlocale(LC_NUMERIC, "");

应将其重置为环境要求的语言环境。

由于您无论如何都依赖于 glibc,因此您可以使用 strverscmp