由localtime引发的函数可重入问题
发布日期:2021-06-28 21:10:55 浏览次数:2 分类:技术文章

本文共 2177 字,大约阅读时间需要 7 分钟。

原文地址: http://blog.csdn.net/cuishumao/article/details/10162603

CSDN为什么没有转载功能呢???

一、先看一个例子

[html] 
 
  1. #include<time.h>  
  2. #include <windows.h>  
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     time_t now;  
  6.     struct tm *tmStart, *tmEnd;  
  7.     if(time(&now)==-1)//函数time返回月历值(格式 struct tm)。若参数是0,函数返回该值,否则将转换的结果保存在参数中。失败返回-1  
  8.         return -1;  
  9.     tmStart = localtime(&now);//把从1970-1-1零点零分到当前时间系统所偏移的秒数时间,转换为本地tm结构体的日历时间  
  10.     Sleep(7);//linux下Sleep改为sleep  
  11.     if(time(&now)==-1)  
  12.         return -1;  
  13.     tmEnd = localtime(&now);  
  14.     //按照预先的想法,tmStart比tmEnd的时间近似1897秒,可是结果并不是我们想要的!!!  
  15.     printf("tmStart时间为:\t%s", asctime(tmStart));  
  16.     printf("tmEnd时间为:\t%s", asctime(tmEnd));  
  17.     getchar();  
  18.     return 0;  
  19. }  
结果是:

(1)在windows、visual studio2010中的结果


(2)在linux、eclipse下的测试结果:


在linux下man localtime截取到的内容是:


       
注意到:
 (1)The  four  functions  asctime(),  ctime(),  gmtime() and localtime() return a pointer to static data and   hence are not thread-safe.
  这几个函数非线程安全的,线程安全的版本是在各函数后面加_r;
 (2)The asctime(), ctime(), gmtime(), and localtime() functions shall return values in   one of two static objects: a broken-down time structure 
     and an array of type char.即返回值保存在静态对象中。
二、不可重入函数
从以上例子的现象可以看出,tmStart指向的内容在后面的localtime中被改变了。也就是使用这种方法,前面的时间丢失了。
同样的问题若出在多线程中程序,自然出现不可预料的结果。
在实时系统中不可重入函数被认为是不安全的函数。
满足下列条件的函数多数是不可重入的:
(1) 函数体内使用了静态的数据结构;
(2)函数体内调用了malloc()或者free()函数;
(3)函数体内调用了标准I/O函数。
 对于这种函数在处理时需要注意:当然最好使用线程安全的函数!
(1)对于这个例子,可以把tmStart的结果拷贝出来。使的该指针不在与localtime关联。
         如:struct tm tmStart_pre;
                memcpy(&tmStart_pre,tmStart,sizeof(struct tm));

(2)通过关中断、信号量(即P、V操作)等手段对其加以保护。

三、编写可重入的函数
(1)受保护的全局变量和静态变量
(2)尽量使用局部变量(例如寄存器、堆栈中的变量);
(3) 在和硬件发生交互的时候,切记执行类似disinterrupt()之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/退出核心”。
(4) 不能调用其它任何不可重入的函数。
(5) 谨慎使用堆栈。

四、与之类似的函数inet_ntoa

[cpp] 
 
  1. void main()  
  2. {  
  3.     struct in_addr b1,b2;  
  4.     b1.s_addr = inet_addr("192.168.1.5");//将一个点分十进制的IP转换成一个长整数型数  
  5.     b2.s_addr = inet_addr("192.168.1.87");  
  6.     char*s1 = inet_ntoa(b1);//将一个in_addr格式的IP转换成一个互联网标准点分格式的字符串  
  7.     char*s2 = inet_ntoa(b2);  
  8.     //当上两句执行完毕之后,s1和s2指向相同的地址,这跟localtime类似  
  9. }  
man inet_ntoa可以看到对它的解释:

The  inet_ntoa() function converts the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation.  The string is returned in
 
a stati-cally allocated buffer,
 which subsequent calls will overwrite.

转载地址:https://blog.csdn.net/yangyangsnr/article/details/78738428 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:查看支持球队一周比赛安排的python脚本
下一篇:自动打开应用程序

发表评论

最新留言

不错!
[***.144.177.141]2024年04月22日 23时15分51秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

原生安卓开发!驱动核心源码详解和Binder超系统学习资源,实战篇 2019-04-29
大牛手把手带你!2021年Android进阶者的新篇章,完整PDF 2019-04-29
太牛了!Android程序员最大的悲哀是什么?面试真题解析 2019-04-29
作为字节跳动面试官,BAT这种大厂履历意味着什么?赶快收藏备战金九银十! 2019-04-29
大牛深入讲解!Android面试中常问的MMAP到底是啥东东?再不刷题就晚了! 2019-04-29
太赞了!你会的还只有初级安卓工程师的技术吗?3面直接拿到offer 2019-04-29
腾讯Android开发面试记录,安卓系列学习进阶视频 2019-04-29
阿里P8架构师的Android大厂面试题总结,醍醐灌顶! 2019-04-29
阿里、腾讯大厂Android面试必问知识点系统梳理,满满干货指导 2019-04-29
阿里大神最佳总结Flutter进阶学习笔记,内容太过真实 2019-04-29
阿里巴巴内部Jetpack宝典意外流出!送大厂面经一份! 2019-04-29
阿里正式启动2021届春季校招!字节跳动Android面试凉凉经,实战解析 2019-04-29
阿里珍藏版Android框架体系架构手写文档,原理+实战+视频+源码 2019-04-29
零基础也能看得懂!2021中级Android开发面试解答,附赠课程+题库 2019-04-29
震惊!靠着这份面试题跟答案,复习指南 2019-04-29
Android最强保活黑科技的最强技术实现,深度解析,值得收藏 2019-04-29
Android架构师必备框架技能核心笔记,面试心得体会 2019-04-29
Android架构师必备框架技能核心笔记,高级面试题+解析 2019-04-29
android热修复框架对比,12年高级工程师的“飞升之路”,含泪整理面经 2019-04-29
Android多线程实现方式及并发与同步,技术详细介绍 2019-04-29