localtime()函数的使用问题
来源:互联网 发布:人工智能用什么语言写 编辑:程序博客网 时间:2024/06/05 05:58
localtime()函数的使用问题
本篇部分内容参考 http://blog.csdn.net/stpeace/article/details/24440329
1. 问题描述
同 “struct tm”的任务,谈谈另一个函数的实现中遇到的问题。
定义一个类Date:
class Date{public: Date() {} Date(int n_year, int n_month, int n_day) { if (!DateFormIsCorrect(n_year, n_month, n_day)) { cout << "Construction failed, the date format is incorrect!\n"; return; } mn_year = n_year; mn_month = n_month; mn_day = n_day; } friend ostream& operator << (ostream &out, Date &date); Date operator + (int n_day); Date operator - (int n_day); int operator - (Date &date);private: bool DateFormIsCorrect(int n_year, int n_month, int n_day); int mn_year, mn_month, mn_day;};
现在来考察 int operator - (Date &date);
的实现问题。
//作用:返回*this 与 date 相差的天数int Date::operator - (Date &date){ //建立两个 tm 类型指针 time_t t_a(0), t_b(0); struct tm *ptm_a = localtime(&t_a), *ptm_b = localtime(&t_b); //两个指针分别代表 *this 与 date ptm_a->tm_year = mn_year - 1900; ptm_a->tm_mon = mn_month - 1; ptm_a->tm_mday = mn_day; ptm_b->tm_year = date.mn_year - 1900; ptm_b->tm_mon = date.mn_month - 1; ptm_b->tm_mday = date.mn_day; //得出相差的时间 t_a = mktime(ptm_a); t_b = mktime(ptm_b); if (t_a < t_b) { t_a = t_a ^ t_b; t_b = t_a ^ t_b; t_a = t_a ^ t_b; } //转换为天数 double d_differ = difftime(t_a, t_b); int n_day = static_cast<int>(d_differ / (24 * 3600 * 1.0)); return n_day;}
这行代码看上去没什么问题,但事实上,无论输入什么,该函数永远返回 0.
2.原因分析
原因出在函数 localtime()
上。
localtime()函数实现有一个问题:
该函数返回的是一个指针,表示某一个地址。大家知道,如果是一个非静态的局部变量,返回它的地址是错误的做法,因为非静态的局部变量在函数返回时,已经被销毁了,它的地址成为无用的地址。因此localtime函数返回的指针只有以下三种可能:要么是一个静态变量的地址,要么是一个全局变量的地址,或者是使用malloc等函数在堆上分配的空间。
对于最后一种情况,因为标准并没有规定可以对localtime返回的地址进行free,所以如果localtime函数是使用malloc函数分配空间的话,程序员不会使用free函数去释放它,因此造成内存泄露,这是不好的做法。
而localtime()返回的就是一个指向静态变量的指针。 也就是说其内部实现大致如此:
struct tm* localtime(const time_t* ptr){ static struct tm ret; // 在这里计算并得到ret的值 return &ret;}
因此不论调用多少次localtime,则它返回的地址都是一样的。只是地址中保存的内容可能不同而已。
3.检验
在函数中插入两行代码:
struct tm *ptm_a = localtime(&t_a), *ptm_b = localtime(&t_b);cout << "ptm_a = " << ptm_a << endl;cout << "ptm_b = " << ptm_b << endl;
最终输出结果:
可知其实 ptm_a
与 ptm_b
指向同一 struct tm
的对象。所以最后得出相差天数为0。
在将 t_b
值改动一下,再做一次实验
time_t t_a(0), t_b(100);//将t_b由0改为100struct tm *ptm_a = localtime(&t_a), *ptm_b = localtime(&t_b);cout << "ptm_a = " << ptm_a << endl;cout << "ptm_b = " << ptm_b << endl;
输出结果
由此可以得出结论:localtime()函数返回的指针全都指向同一个位置,因此如果在程序中连续使用,则很可能会出错!
4.解决办法
方法一:
一次只调用一个 localtime()
函数,调用完毕后立即取出返回值的内容。
即改为如下形式:
time_t t_a(0), t_b(0);struct tm *ptm_a = localtime(&t_a), *ptm_b;ptm_a->tm_year = mn_year - 1900;ptm_a->tm_mon = mn_month - 1;ptm_a->tm_mday = mn_day;t_a = mktime(ptm_a);//立即提取出信息ptm_b = localtime(&t_b);ptm_b->tm_year = date.mn_year - 1900;ptm_b->tm_mon = date.mn_month - 1;ptm_b->tm_mday = date.mn_day;//t_a = mktime(ptm_a);t_b = mktime(ptm_b);
最终可得出正确结果。
方法二:
使用其他的函数 localtime_s()
以及 localtime()_s
①.errno_t localtime_s(struct tm* _tm,const time_t *time ); (since c11)
该函数是在windows下使用的函数,需要两个参数。其中 _tm指向要填充的时间结构的指针,time指向存储的时间。 使用如下:
time_t t_a(0), t_b(0);struct tm ptm_a , ptm_b;//注意并没有用指针localtime_s(&ptm_a, &t_a);localtime_s(&ptm_b, &t_b);ptm_a.tm_year = mn_year - 1900;ptm_a.tm_mon = mn_month - 1;ptm_a.tm_mday = mn_day;t_a = mktime(ptm_a);ptm_b.tm_year = date.mn_year - 1900;ptm_b.tm_mon = date.mn_month - 1;ptm_b.tm_mday = date.mn_day;t_a = mktime(&ptm_a);t_b = mktime(&ptm_b);
注意,这里并没有用 struct tm *
而是直接定义了两个 tm
的变量。 这是因为用指针的话会出现对未初始化的指针的访问问题。
②struct tm *localtime_r(const time_t*restrict timer, struct tm *restrict result);
大致相同,不过该函数是在linux下用的。
- localtime()函数的使用问题
- 由localtime引发的函数可重入问题
- 由localtime引发的函数可重入问题
- 由localtime引发的函数可重入问题
- localtime函数在vc++2005中的使用问题
- 关于时间函数localtime()返回值的注意问题
- localtime和gmtime函数使用
- C++使用localtime函数需要注意的地方
- C++使用localtime函数需要注意的地方
- C++使用localtime函数需要注意的地方
- localtime、localtime_s、localtime_r的使用
- localtime ()函数
- localtime函数
- localtime 问题
- localtime函数中的返回指针的思考
- linux上localtime函数返回的指针
- C++使用localtime函数需要注意的地方http://blog.csdn.net/shellching/article/details/8114266
- perl 中localtime()函数解释
- HDU1024 ——Max Sum Plus Plus(动态规划)
- 多线程编程小结(一)
- java小案例:计算你现在到出生的天数
- Linux下的文件描述符与文件指针及其区别
- 漫谈递归:递归的思想
- localtime()函数的使用问题
- vb.net指定范围内获取随机数
- git学习及基本入门
- re库主要功能函数
- 深度学习之标注工具【Qt版】
- 数组删除重复的数字1方法一:
- 集成学习(Ensemble Learning)
- Ubuntu安装使用google代码规范工具cpplint
- Android Studio安装新的字体