strerror執行緒安全分析
導讀
strerror是否執行緒安全了?
答案是NO,但它有個執行緒安全的版本:strerror_r。藉助Linux的man,即可看到詳情:
#include 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
int main() { #ifdef _GNU_SOURCE
printf(“_GNU_SOURCE defined #else
printf(“_GNU_SOURCE not defined #endif
#ifdef _LIBC_REENTRANT
printf(“_LIBC_REENTRANT defined #else
printf(“_LIBC_REENTRANT not defined #endif
#ifdef _LIBC
printf(“_LIBC defined #else
printf(“_LIBC not defined #endif
return 0; } |
附1:strerror原始碼
// glibc-2.14stringstrerror.c #include
/* 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.14string\_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 0 || 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
numbuf[20] = ` `; 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 { *q++ = `-`; ++unklen; }
if (unklen memcpy (q, p, MIN ((size_t) (&numbuf[21] – p), buflen – unklen));
/* Terminate the string in any case. */ if (buflen > 0) buf[buflen – 1] = ` `;
return buf; }
return (char *) _(_sys_errlist_internal[errnum]); } weak_alias (__strerror_r, strerror_r) libc_hidden_def (__strerror_r) |
相關文章
- Linux下的strerror是否執行緒安全?LinuxError執行緒
- 執行緒3--執行緒安全執行緒
- 執行緒安全和執行緒不安全理解執行緒
- 執行緒安全執行緒
- 多執行緒系列之 執行緒安全執行緒
- iOS 多執行緒之執行緒安全iOS執行緒
- iOS多執行緒之執行緒安全iOS執行緒
- Java執行緒(一):執行緒安全與不安全Java執行緒
- 【多執行緒總結(二)-執行緒安全與執行緒同步】執行緒
- 什麼是執行緒安全和執行緒不安全執行緒
- 【Java多執行緒】執行緒安全的集合Java執行緒
- 執行緒安全(二)執行緒
- Java執行緒安全Java執行緒
- Java - 執行緒安全Java執行緒
- 多執行緒-執行緒安全問題的產生原因分析以及同步程式碼塊的方式解決執行緒安全問題執行緒
- Java 多執行緒基礎(四)執行緒安全Java執行緒
- iOS多執行緒安全-13種執行緒鎖?iOS執行緒
- 多執行緒,你覺得你安全了?(執行緒安全問題)執行緒
- PHP的執行緒安全與非執行緒安全版本的區別PHP執行緒
- 執行緒安全性執行緒
- 多執行緒安全(一)執行緒
- 執行緒安全操作HashMap執行緒HashMap
- java執行緒安全LockJava執行緒
- EntityFrameworkDbContext執行緒安全FrameworkContext執行緒
- 容器不是執行緒安全執行緒
- 併發程式設計之多執行緒執行緒安全程式設計執行緒
- 小度分享-【多執行緒工作及執行緒安全】執行緒
- 多執行緒與高併發(二)執行緒安全執行緒
- iOS開發基礎——執行緒安全(執行緒鎖)iOS執行緒
- 併發與多執行緒之執行緒安全篇執行緒
- SpringMVC中出現的執行緒安全問題分析SpringMVC執行緒
- ConcurrentHashMap執行緒安全機制以及原始碼分析HashMap執行緒原始碼
- Java併發(十七)----變數的執行緒安全分析Java變數執行緒
- shared_ptr的執行緒安全性分析執行緒
- Java 執行緒池執行原理分析Java執行緒
- 什麼時候執行緒不安全?怎樣做到執行緒安全?怎麼擴充套件執行緒安全的類?執行緒套件
- [短文速讀 -5] 多執行緒程式設計引子:程式、執行緒、執行緒安全執行緒程式設計
- Java併發實戰一:執行緒與執行緒安全Java執行緒