strerror线程安全分析
导读
strerror是否线程安全了?
答案是NO,但它有个线程安全的版本:strerror_r。借助Linux的man,即可看到详情:
#include <string.h> char *strerror(int errnum); int strerror_r(int errnum, char *buf, size_t buflen); /* GNU-specific */ |
那么,在多线程中使用strerror是否安全了?答案是不一定,一定情况下也是非常安全的。
不安全会造成内存违规访问吗?也就是会发生SIGSEGV吗?答案是NO,仍是内存安全的,但是可能会返回错乱的字符串。
那么,在多线程程序中,什么情况下使用strerror是绝对安全的了?如果参数errnum是一个已知的errno,则使用strerror是绝对安全的,也就是会返回期待的字符串,而不会出现乱码。
对比strerror源码,是因为strerror会在下述直接返回:
if (__builtin_expect (ret != NULL, 1)) return ret; |
而这走的是_strerror_r中的分支:
return (char *) _(_sys_errlist_internal[errnum]); |
errno是否线程安全?
答案是不一定,取决于编译宏:
# if !defined _LIBC || defined _LIBC_REENTRANT /* When using threads, errno is a per-thread value. */ # define errno (*__errno_location ()) # endif |
可以通过下段小代码,来确定默认时是否有定义,如果没有,则需要在编译时加上:
#include <stdio.h> int main() { #ifdef _GNU_SOURCE printf("_GNU_SOURCE defined\n"); #else printf("_GNU_SOURCE not defined\n"); #endif #ifdef _LIBC_REENTRANT printf("_LIBC_REENTRANT defined\n"); #else printf("_LIBC_REENTRANT not defined\n"); #endif #ifdef _LIBC printf("_LIBC defined\n"); #else printf("_LIBC not defined\n"); #endif return 0; } |
附1:strerror源码
// glibc-2.14\string\strerror.c #include <errno.h> /* Return a string describing the errno code in ERRNUM. The storage is good only until the next call to strerror. Writing to the storage causes undefined behavior. */ libc_freeres_ptr (static char *buf); char * strerror (errnum) int errnum; { char *ret = __strerror_r (errnum, NULL, 0); int saved_errno; if (__builtin_expect (ret != NULL, 1)) return ret; saved_errno = errno; if (buf == NULL) buf = malloc (1024); __set_errno (saved_errno); if (buf == NULL) return _("Unknown error"); return __strerror_r (errnum, buf, 1024); } |
附2:__strerror_r源码
// glibc-2.14\string\_strerror.c /* Return a string describing the errno code in ERRNUM. */ char * __strerror_r (int errnum, char *buf, size_t buflen) { if (__builtin_expect (errnum < || errnum >= _sys_nerr_internal || _sys_errlist_internal[errnum] == NULL, 0)) { /* Buffer we use to print the number in. For a maximum size for `int' of 8 bytes we never need more than 20 digits. */ char numbuf[21]; const char *unk = _("Unknown error "); size_t unklen = strlen (unk); char *p, *q; bool negative = errnum < 0; numbuf[20] = '\0'; p = _itoa_word (abs (errnum), &numbuf[20], 10, 0); /* Now construct the result while taking care for the destination buffer size. */ q = __mempcpy (buf, unk, MIN (unklen, buflen)); if (negative && unklen < buflen) { *q++ = '-'; ++unklen; } if (unklen < buflen) memcpy (q, p, MIN ((size_t) (&numbuf[21] - p), buflen - unklen)); /* Terminate the string in any case. */ if (buflen > 0) buf[buflen - 1] = '\0'; return buf; } return (char *) _(_sys_errlist_internal[errnum]); } weak_alias (__strerror_r, strerror_r) libc_hidden_def (__strerror_r) |
strerror线程安全分析的更多相关文章
- Java线程问题分析定位
Java线程问题分析定位 分析步骤: 1.使用top命令查看系统资源占用情况,发现Java进程占用大量CPU资源,PID为11572: 2.显示进程详细列表命令:ps -mp 11572 -o THR ...
- Android系统--输入系统(七)Reader_Dispatcher线程启动分析
Android系统--输入系统(七)Reader_Dispatcher线程启动分析 1. Reader/Dispatcher的引入 对于输入系统来说,将会创建两个线程: Reader线程(读取事件) ...
- Android系统--输入系统(十三)Dispatcher线程情景分析_Reader线程传递事件
Android系统--输入系统(十三)Dispatcher线程情景分析_Reader线程传递事件 1. 输入按键 我们知道Android系统的按键分为三类:(1)Global Key;(2)Syste ...
- Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理
Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理 1. 回顾 我们知道Android输入系统是Reader线程通过驱动程序得到上报的输入事件,还要经过处理 ...
- Spring中获取request的几种方法,及其线程安全性分析
前言 本文将介绍在Spring MVC开发的web系统中,获取request对象的几种方法,并讨论其线程安全性. 原创不易,如果觉得文章对你有帮助,欢迎点赞.评论.文章有疏漏之处,欢迎批评指正. 欢迎 ...
- 【转】java线上程序排错经验2 - 线程堆栈分析
前言 在线上的程序中,我们可能经常会碰到程序卡死或者执行很慢的情况,这时候我们希望知道是代码哪里的问题,我们或许迫切希望得到代码运行到哪里了,是哪一步很慢,是否是进入了死循环,或者是否哪一段代码有问题 ...
- [No000016E]Spring 中获取 request 的几种方法,及其线程安全性分析
前言 本文将介绍在Spring MVC开发的web系统中,获取request对象的几种方法,并讨论其线程安全性. 原创不易,如果觉得文章对你有帮助,欢迎点赞.评论.文章有疏漏之处,欢迎批评指正. 欢迎 ...
- java线程dump分析工具
jstack和线程dump分析 java程序性能分析之thread dump和heap dump 一.[内存dump] jmap –dump:live,format=b,file=heap.bin ...
- Spring中获取request的几种方法,及其线程安全性分析(山东数漫江湖)
前言 本文将介绍在Spring MVC开发的web系统中,获取request对象的几种方法,并讨论其线程安全性. 原创不易,如果觉得文章对你有帮助,欢迎点赞.评论.文章有疏漏之处,欢迎批评指正. 欢迎 ...
随机推荐
- ThinkPHP 配置详解
3.0 ThinkPHP配置详解 3.1 入口文件的配置 一般不建议在入口文件做过多的配置,但可以重新定义一些系统常量,以下简单介绍几个常用的系统常量. 1.APP_PATH 默认情况下,框架的项 ...
- 如何实现查询显示N个工作日有效期内的数据
功能点分析:要显示N个工作日有效期内的数据,需要考虑: 1. 可以给每条数据增加一个有效期时间字段,查询时只显示有效期之前的数据,如有效期为七天,数据的创建时间是2014-07-21,那七个工作日有效 ...
- 脱壳系列(一) - CrypKeySDK 壳
程序: 运行 用 PEiD 载入程序 PEid 显示找不到相关的壳 脱壳: 用 OD 载入程序 这个是壳的入口地址 因为代码段的入口地址为 00401000 这三个是壳增加的区段 按 F8 往下走程序 ...
- JAVA实现汉字转换为拼音 pinyin4j/JPinyin
在项目中经常会遇到需求用户输入汉字后转换为拼音的场景,比如说通讯录,就会要求按名字首字符发音排序,如果自己写实现这方面的功能是个很好大的工程,还好网上有公开的第三方jar支持转换,结合网上很多前辈的代 ...
- [转]DWZ表单验证规则一览表(留着自己用)
<form onsubmit="return validateCallback(this)" class="pageForm" action=" ...
- flutter android keystore
keytool -genkey -v -keystore E:/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key k ...
- 3DMAX 处理反面
问题起源:从3DMAX导出一个模型为FBX后,在U3D中看到模型很奇怪的透视了,能看到背面看不到正面,这不法线问题,而是面反了. 即然是面反了,为什么在MAX中看起来是正确的呢? 应该是开启了双面模式 ...
- 网卡流量监控脚本 ( Python )
#!/usr/bin/env python # coding: utf-8 # author: Xiao Guaishou try: import psutil except ImportError: ...
- Elasticsearch-PHP 概述
最近在学习使用Elasticsearch,并且是和PHP一起使用的,看到了Elasticsearch-PHP,其实是Elasticsearch为PHP提供的客户端,那么我们来学习一下API文档,如何在 ...
- 设置Windows开机自动启动VirtualBox虚拟机系统
如果常用VirtualBox虚拟机系统的话,设置随开机启动也是很方便的.不需要打开VirtualBox窗口,直接启动VirtualBox虚拟机系统就可以了. 设置开机自启动VirtualBox虚拟机系 ...