C库的非线程安全函数,以localtime函数为例
•C++
1357
0
以localtime
函数为例,有如下代码:
#include <iostream>
#include <time.h>
int main() {
time_t start = time(NULL);
time_t end = start + 1000;
struct tm* ptm_start = localtime(&start); // <--------
struct tm* ptm_end = localtime(&end); // <--------
char str_start[64] = { 0 };
char str_end[64] = { 0 };
strftime(str_start, 64, "%H:%M:%S", ptm_start);
strftime(str_end, 64, "%H:%M:%S", ptm_end);
printf("start: %s\n", str_start);
printf(" end: %s\n", str_end);
return 0;
}
输出结果:
$ ./out
start: 17:52:55
end: 17:52:55
两个时间差了1000秒,但是输出结果却一样。
localtime
函数签名如下:
struct tm* localtime(const time_t* timep);
函数返回的是一个指针,但是外部却不需要释放这个指针指向的内存,因此其内部使用了一个全局变量或函数内部的静态变量。
因此两次调用该函数,第2次的结果就覆盖了第1次的结果(二者返回的指针指向同一个地址)。
上述例子中有如下条件成立:
ptm_start == ptm_end; // true
使用线程安全的函数localtime_r
替代。
#include <iostream>
#include <time.h>
int main() {
time_t start = time(NULL);
time_t end = start + 1000;
struct tm tm_start;
struct tm tm_end;
localtime_r(&start, &tm_start);
localtime_r(&end, &tm_end);
char str_start[64] = { 0 };
char str_end[64] = { 0 };
strftime(str_start, 64, "%H:%M:%S", &tm_start);
strftime(str_end, 64, "%H:%M:%S", &tm_end);
printf("start: %s\n", str_start);
printf(" end: %s\n", str_end);
return 0;
}
输出结果正确
$ ./out
start: 17:55:21
end: 18:12:01
C库中存在一些非线程安全函数,因为最初编写CRT时还没有多线程技术,所以很多函数内部使用了全局变量或函数内部的静态变量。随着多线程技术的出现,很多函数都有了对应的多线程安全版本。