C语言 如何在当前区域设置中使用strerror_l?

wwwo4jvm  于 2023-11-16  发布在  其他
关注(0)|答案(2)|浏览(128)

我正在修复一些使用strerror的Linux代码我发现strerror_rstrerror_l都是线程安全的。由于strerror_r的定义不同,(取决于_GNU_SOURCE它是不同的定义)我想使用较新的strerror_l函数,但是我应该如何获得当前区域设置的locale_t对象呢?我没有使用iconv或任何东西,只是普通的libc,我不知道如何获得“default locale”对象(我不关心错误是用什么语言打印的,我只想要一个人类可读的字符串)。

hiz5n14c

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)

  1. static locale_t locale;
  2. bool MyStrerrorInit(void)
  3. {
  4. locale = newlocale(LC_ALL_MASK,"",(locale_t)0);
  5. if (locale == (locale_t)0) {
  6. return false;
  7. }
  8. return true;
  9. }
  10. char * MyStrerror(int error)
  11. {
  12. return strerror_l(error, locale);
  13. }

字符串

展开查看全部
dly7yett

dly7yett2#

可以使用POSIX uselocale

  1. 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行为,提供了一个没有未定义行为的版本,并讨论了替代方案。
一个明显的不是线程安全的版本:

  1. locale_t locale = uselocale((locate_t)0);
  2. if (locale == LC_GLOBAL_LOCALE) {
  3. strerror(errno);
  4. } else {
  5. strerror_l(errno, locale);
  6. }


线程安全版本:

  1. locale_t locale = uselocale((locate_t)0);
  2. locale_t copy = loc;
  3. if (copy == LC_GLOBAL_LOCALE) {
  4. copy = duplocale(copy);
  5. }
  6. strerror_l(errno, copy);
  7. if (loc == LC_GLOBAL_LOCALE) {
  8. freelocale(copy);
  9. }


这里有一个完整的工作示例,来自@TavianBarnes。

展开查看全部

相关问题