Linux下strtod出错与C++国际化问题

本文介绍了在Linux系统中遇到的一个与国际化有关的bug,具体表现为使用strtod函数时出现错误。问题源于德语环境下的数字分隔符习惯,小数点用逗号而非句点。解决方案包括重置LC_ALL为C或POSIX,仅修改LC_NUMERIC,或者改变LANG环境变量。通过分析locale环境变量的优先级,帮助理解国际化设置对程序的影响。
摘要由CSDN通过智能技术生成

  • 问题

最近,公司的GUI程序(基于wxWidgets)在Linux下出来一个bug,说起来有点不可思议。

类似下面的一块代码

 const char* str="0.06";
 char* end=NULL;
 double d = strtod(str, &end);
 printf("str=%s, end=%s, %f\n", str, end, d);

输出结果是:

str=0.06, end=.06, 0,000000

难道strtod会出错了吗?不可能吧?!

为了确认这个问题,写一个小程序在客户机子上测试。

test 1:

// main.cpp

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
 const char* str="0.06";
 char* end=NULL;
 double d = strtod(str, &end);
 printf("str=%s, end=%s, %f\n", str, end, d);
 return 0;
}

编译并运行这个测试程序, 发现结果完全正常。说明GUI程序本身存在某种问题。

后来客户怀疑可能与locale设置相关,就更改了locale设置。客户的机子默认是德语,改成环境变量LC_ALL=C后,GUI程序能够正常运行了!微笑

strtod在德语环境下会出错?!!

  • 重现bug

简单修改测试程序 main.cpp,得到 

test 2

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int main(int argc, char* argv[])
{
	printf("LC_ALL:%s\n"
		"LC_CTYPE:%s\n"
		"LC_MESSAGES:%s\n"
		,setlocale(LC_ALL, NULL)
		,setlocale(LC_CTYPE, NULL)
		,setlocale(LC_MESSAGES, NULL)
		);

	const char* str="0.06";
	char* end=NULL;
	double d = strtod(str, &end);
	printf("str=%s, end=%s, %f\n", str, end, d);
	return 0;
}

为了模拟客户的环境,设置当前的LANG为德语:

export LANG=de_DE.UTF-8

运行程序,输出结果是:

LC_ALL:C
LC_CTYPE:C
LC_MESSAGES:C
str=0.06, end=, 0,06

这说明test 1 和test 2在进入main函数的时候,程序自身的locale是C。

难道因为wx程序里面的locale变了,所以出错了吗?
但是我们自身的程序并没有改动locale啊。

在wxApp::OnInit的重载函数里面打印当前的locale看看
bool App::OnInit () 
{   
    wxLogDebug("Current locale : %s", setlocale(LC_ALL, NULL));
结果发现wx程序的默认locale是 de_DE.UTF-8, 也就是系统的locale设置。

glibc下只能通过setlocale来修改程序的locale设置,所以wx程序肯定在初始化的过程中调用或间接调用了setlocale函数。
直接gdb下设置setlocale函数断点,  终于找到了出错的位置app.cpp:420 微笑

查看gtk中gtk_set_locale的manual

 gtk_set_locale ()
gchar*              gtk_set_locale                      (void);

Initializes internationalization support for GTK+. gtk_init() automatically does this, so there is typically no point in calling this function.

If you are calling this function because you changed the locale after GTK+ is was initialized, then calling this function may help a bit. (Note, however, that changing the locale after GTK+ is initialized may produce inconsistent results and is not really supported.)

In detail - sets the current locale according to the program environment. This is the same as calling the C library function setlocale (LC_ALL, "") but also takes care of the loc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值