我正在修复一些使用strerror的Linux代码我发现strerror_r和strerror_l都是线程安全的。由于strerror_r的定义不同,(取决于_GNU_SOURCE它是不同的定义)我想使用较新的strerror_l函数,但是我应该如何获得当前区域设置的locale_t对象呢?我没有使用iconv或任何东西,只是普通的libc,我不知道如何获得“default locale”对象(我不关心错误是用什么语言打印的,我只想要一个人类可读的字符串)。
strerror
strerror_r
strerror_l
_GNU_SOURCE
locale_t
iconv
hiz5n14c1#
如果将“”传递给locale参数,newlocale将分配一个locale对象,该对象设置为当前本地locale[1][1][http://pubs.opengroup.org/onlinepubs/9699919799/functions/newlocale.html](http://pubs.opengroup.org/onlinepubs/9699919799/functions/newlocale.html)
static locale_t locale;bool MyStrerrorInit(void){ locale = newlocale(LC_ALL_MASK,"",(locale_t)0); if (locale == (locale_t)0) { return false; } return true;} char * MyStrerror(int error){ return strerror_l(error, locale);}
static locale_t locale;
bool MyStrerrorInit(void)
{
locale = newlocale(LC_ALL_MASK,"",(locale_t)0);
if (locale == (locale_t)0) {
return false;
}
return true;
char * MyStrerror(int error)
return strerror_l(error, locale);
字符串
dly7yett2#
可以使用POSIX uselocale:
uselocale
strerror_l(errno, uselocale((locate_t)0));
字符串@TavianBarnes在评论中指出,这段代码可能会表现出未定义的行为:[CX][Option Start]如果strerror_l()的区域设置参数是特殊的区域设置对象LC_GLOBAL_LOCALE或不是有效的区域设置对象句柄,则行为未定义。[Option End]https://pubs.opengroup.org/onlinepubs/9699919799/functions/strerror.html的成功完成后,uselocale()函数应返回一个线程本地语言环境的句柄,该句柄在进入函数时用作调用线程的当前语言环境,或者如果没有使用线程本地语言环境,则返回LC_GLOBAL_LOCALE。https://pubs.opengroup.org/onlinepubs/9699919799/functions/uselocale.html的Use of LC_GLOBAL_LOCALE with *_l() functions阐明了当给定LC_GLOBAL_LOCALE作为locale时*_l()函数的UB行为,提供了一个没有未定义行为的版本,并讨论了替代方案。一个明显的不是线程安全的版本:
LC_GLOBAL_LOCALE
locale
*_l()
locale_t locale = uselocale((locate_t)0);if (locale == LC_GLOBAL_LOCALE) { strerror(errno);} else { strerror_l(errno, locale);}
locale_t locale = uselocale((locate_t)0);
if (locale == LC_GLOBAL_LOCALE) {
strerror(errno);
} else {
strerror_l(errno, locale);
型线程安全版本:
locale_t locale = uselocale((locate_t)0);locale_t copy = loc;if (copy == LC_GLOBAL_LOCALE) { copy = duplocale(copy);}strerror_l(errno, copy);if (loc == LC_GLOBAL_LOCALE) { freelocale(copy);}
locale_t copy = loc;
if (copy == LC_GLOBAL_LOCALE) {
copy = duplocale(copy);
strerror_l(errno, copy);
if (loc == LC_GLOBAL_LOCALE) {
freelocale(copy);
型这里有一个完整的工作示例,来自@TavianBarnes。
2条答案
按热度按时间hiz5n14c1#
如果将“”传递给locale参数,newlocale将分配一个locale对象,该对象设置为当前本地locale[1]
[1][http://pubs.opengroup.org/onlinepubs/9699919799/functions/newlocale.html](http://pubs.opengroup.org/onlinepubs/9699919799/functions/newlocale.html)
字符串
dly7yett2#
可以使用POSIX
uselocale
:字符串
@TavianBarnes在评论中指出,这段代码可能会表现出未定义的行为:
[CX][Option Start]如果strerror_l()的区域设置参数是特殊的区域设置对象LC_GLOBAL_LOCALE或不是有效的区域设置对象句柄,则行为未定义。[Option End]
https://pubs.opengroup.org/onlinepubs/9699919799/functions/strerror.html的
成功完成后,uselocale()函数应返回一个线程本地语言环境的句柄,该句柄在进入函数时用作调用线程的当前语言环境,或者如果没有使用线程本地语言环境,则返回LC_GLOBAL_LOCALE。
https://pubs.opengroup.org/onlinepubs/9699919799/functions/uselocale.html的
Use of LC_GLOBAL_LOCALE with *_l() functions阐明了当给定
LC_GLOBAL_LOCALE
作为locale
时*_l()
函数的UB行为,提供了一个没有未定义行为的版本,并讨论了替代方案。一个明显的不是线程安全的版本:
型
线程安全版本:
型
这里有一个完整的工作示例,来自@TavianBarnes。