printf的重入问题及解决方法 http://blog.csdn.net/iefswang/article/details/7523458
来源:互联网 发布:开源直播系统源码 php 编辑:程序博客网 时间:2024/06/16 03:57
printf的重入问题及解决方法
![](http://static.blog.csdn.net/images/category_icon.jpg)
一、可重入函数
1)什么是可重入性?
可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误。相反, 不可重入(non-reentrant)函数不能由超过一个任务所共享。
可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。
2)可重入函数:
不为连续的调用持有静态数据。
不返回指向静态数据的指针;所有数据都由函数的调用者提供。
使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。
如果必须访问全局变量,记住利用互斥信号量来保护全局变量。
绝不调用任何不可重入函数。
3)不可重入函数:
函数中使用了静态变量,无论是全局静态变量还是局部静态变量。
函数返回静态变量。
函数中调用了不可重入函数。
函数体内使用了静态的数据结构;
函数体内调用了malloc()或者free()函数;
函数体内调用了其他标准I/O函数。
函数是singleton中的成员函数而且使用了不使用线程独立存储的成员变量 。
总的来说,如果一个函数在重入条件下使用了未受保护的共享的资源,那么它是不可重入的。
常见的不可重入函数有:
printf --------引用全局变量stdout
malloc --------全局内存分配表
free --------全局内存分配表
在unix里面通常都有加上_r后缀的同名可重入函数版本。
把一个不可重入函数变成可重入的唯一方法是用可重入规则来重写他。
二、函数编写规范
1 :对所调用函数的错误返回码要仔细、全面地处理
2 :明确函数功能,精确(而不是近似)地实现函数设计
3 :编写可重入函数时,应注意局部变量的使用(如编写C/C++ 语言的可重入函数时,应使用auto 即缺省态局部变量或寄存器变量)
说明:编写C/C++语言的可重入函数时,不应使用static局部变量,否则必须经过特殊处理,才能使函数具有可重入性。
4 :编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P 、V 操作)等手段对其加以保护
说明
5 :在同一项目组应明确规定对接口函数参数的合法性检查应由函数的调用者负责还是由接口函数本身负责,缺省是由函数调用者负责
说明
6 :防止将函数的参数作为工作变量
说明:将函数的参数作为工作变量,有可能错误地改变参数内容,所以很危险。对必须改变的参数,最好先用局部变量代之,最后再将该局部变量的内容赋给该参数。
示例:如下函数的实现就不太好。
void sum_data( unsigned int num, int *data, int *sum )
{
unsigned int count;
*sum = 0;
for (count = 0; count < num; count++)
{
*sum += data[count]; // sum成了工作变量,不太好。
}
}
若改为如下,则更好些。
void sum_data( unsigned int num, int *data, int *sum )
{
unsigned int count ;
int sum_temp;
sum_temp = 0;
for (count = 0; count < num; count ++)
{
sum_temp += data[count];
}
*sum = sum_temp;
}
7 :函数的规模尽量限制在200 行以内
说明:不包括注释和空格行。
8 :一个函数仅完成一件功能
9 :为简单功能编写函数
说明:虽然为仅用一两行就可完成的功能去编函数好象没有必要,但用函数可使功能明确化,增加程序可读性,亦可方便维护、测试。
示例:如下语句的功能不很明显。
value = ( a > b ) ? a : b ;
改为如下就很清晰了。
int max (int a, int b)
{
return ((a > b) ? a : b);
}
value = max (a, b);
或改为如下。
#define MAX (a, b) (((a) > (b)) ? (a) : (b))
value = MAX (a, b);
10:不要设计多用途面面俱到的函数
说明:多功能集于一身的函数,很可能使函数的理解、测试、维护等变得困难。
11:函数的功能应该是可以预测的,也就是只要输入数据相同就应产生同样的输出
- printf的重入问题及解决方法 http://blog.csdn.net/iefswang/article/details/7523458
- java system.out.printf()的使用方法 http://blog.csdn.net/wangchangshuai0010/article/details/8647503
- Servlet 中文乱码问题及解决方案剖析--转载--http://blog.csdn.net/xiazdong/article/details/7217022
- printf的重入问题及解决方法
- 进程线程及堆栈关系的总结 http://blog.csdn.net/echoisland/article/details/6403763
- Shellcode的原理及编写http://blog.csdn.net/maotoula/article/details/18502679
- selenium使用中遇到的问题,转自:http://blog.csdn.net/funi16/article/details/9036753
- boost的安装问题 http://blog.csdn.net/begtostudy/article/details/1879213
- 类模版的分离编译问题 http://blog.csdn.net/woshishuizzz/article/details/8648440
- MFC主线程使用WaitForSingleObject阻塞的问题 http://blog.csdn.net/sysprogram/article/details/17383455
- 出现chkstk.asm问题的解决方式之一http://blog.csdn.net/feixuedudiao/article/details/8625039
- 检查C语言的内存问题 参考网址:http://blog.csdn.net/sduliulun/article/details/7732906
- 使用dup和dup2重定向和还原 http://blog.csdn.net/kangear/article/details/24098315
- android listview 连续调用 getview问题分析及解决。http://blog.csdn.net/f8376904110/article/details/6460934
- PrintStream: - shichunle的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/shichunle/article/details/6754930
- 浅析C++中虚函数的调用及对象的内部布局http://blog.csdn.net/starlee/article/details/2089358
- Eclipse常见的颜色设置及常用快捷键 转自:http://blog.csdn.net/badboy1110/article/details/6875891
- SQLite数据库的挂接及常用命令(转自:http://blog.csdn.net/windone0109/article/details/5514948)
- Android 之fragment显示 FragmentTransaction show and hide
- EXCEL函数大全
- [Cryptography] Introduction
- 【六级】:六级翻译复习
- 【jQuery】:contains(text)过滤选择器
- printf的重入问题及解决方法 http://blog.csdn.net/iefswang/article/details/7523458
- 从面向对象六大原则开始
- 【android】第一个简单的轮子(多图展示控件--ImageViewGroup)
- “约定优于配置”与Magento
- showForAllUsers
- 天方夜谭-第一夜
- 数据结构和算法经典100题-第23题
- Android中的加载动画效果
- hadoop入门--简单的MapReduce案例