redstone9910 该用户已被删除
21
 
提示: 作者被禁止或删除 内容自动屏蔽
 

回复

1672

帖子

0

TA的资源

裸片初长成(初级)

22
 

回复 21楼 redstone9910 的帖子

是的,那么请让我们再深入一些,如何?
函数看到fmt这个字串里面的转义字符%,就去寻找下一个参数。如果调用函数的时候并没有传递这个参数,函数会取得一个随机值对应这个转义字符。
问题是,这个随机值从哪里取出来的?
此帖出自编程基础论坛
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

23
 
不错,学习了
此帖出自编程基础论坛
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(初级)

24
 
不错,下来晒晒。
此帖出自编程基础论坛
 
 
 

回复
redstone9910 该用户已被删除
25
 
提示: 作者被禁止或删除 内容自动屏蔽
 
 
 

回复
redstone9910 该用户已被删除
26
 
提示: 作者被禁止或删除 内容自动屏蔽
 
 
 

回复
redstone9910 该用户已被删除
27
 
提示: 作者被禁止或删除 内容自动屏蔽
 
 
 

回复

1672

帖子

0

TA的资源

裸片初长成(初级)

28
 

明天放出这个问题的标准答案。

这个问题涉及到体系结构和编译器的实现,不是一句话可以说清楚的,
以后还会详细讨论到给函数传递参数的一些微妙的实现。
此帖出自编程基础论坛
 
 
 

回复

85

帖子

0

TA的资源

一粒金砂(高级)

29
 
从大一到现在,学了一年半的c++和c,楼主出了2掌,我都不会,真是忏悔啦!
看来要回去再研究下c才行啦,楼主的问题真是有深度!

继续关注楼主的C语言降龙十八掌(能学到老师不会教的东西,真是很好的知识,O(∩_∩)O哈哈~)!
此帖出自编程基础论坛
 
 
 

回复
redstone9910 该用户已被删除
30
 
提示: 作者被禁止或删除 内容自动屏蔽
 
 
 

回复

799

帖子

0

TA的资源

纯净的硅(中级)

31
 
很好很强大!
支持下!
此帖出自编程基础论坛
 
 
 

回复

24

帖子

0

TA的资源

一粒金砂(中级)

32
 
高手啊
此帖出自编程基础论坛
 
 
 

回复

1672

帖子

0

TA的资源

裸片初长成(初级)

33
 

本期小结

本期小结:
printf函数的实现,大致是这样的:

int printf(const char *fmt, ...)
{
        char printf_buf[1024];
        va_list args;
        int printed;

        va_start(args, fmt);
        printed = vsprintf(printf_buf, fmt, args);
        va_end(args);

        puts(printf_buf);

        return printed;
}

我们可以看到,它是调用vsprintf函数,将第二个参数以后的参数,按格式化字串输出,然后在终端显示出来。如果格式化字串中有多余的%字符,而没有传递相应的参数,会获得一个随机数。
这里有两个问题:首先,如果这个多余的%转义字符是一个“%s”,后果是怎样的呢?后果就是访问了一个没有初始化的指针“野指针”。对于8051/ARM7这样没有内存处理单元(MMU)的处理器,会显示不可预料的内容。但对于MIPS/X86这样有MMU的处理器,CPU内部的硬件线路会判断这个指针是否合法。如果是一个非法指针,会引发系统抛出一个异常(Exception),从而导致进程崩溃(process crash),也就是Windows下常见的“该程序执行了非法操作”。而在操作系统内核中发生了这种错误,会引发内核panic,类似Windows的蓝屏死机的概念,系统彻底崩溃。前面提到的,出现这个问题的核心交换机上,就是由于出现内核panic而死机重启的。
那么,随机数是从哪里获得的呢?
这个问题和体系结构密切相关了。对于x86,我们知道,参数是通过堆栈传递的,那么也就是从没有初始化的堆栈存储区取得的。而对于MIPS/ARM这样的RISC处理器,系统会占用几个寄存器作为传递参数用,如果不够用再通过堆栈传递。因此,在RISC处理器上,错误的参数还有可能从寄存器传递过来。8051是CISC处理器中的一个异类,C51编译器的函数参数传递,使用了R4到R7的四个寄存器,和RISC类似,这点要注意。
最后,请大家吸取一个教训,printf的第一个参数char *fmt,指针指向的内容一定要可控,千万不要用计算机自动生成的内容。

下期预告:strcpy函数是C标准库里面的一个常用的字符串拷贝函数。如果让你来写一个,你会写成什么样子呢?
此帖出自编程基础论坛

赞赏

1

查看全部赞赏

 
 
 

回复

90

帖子

0

TA的资源

一粒金砂(初级)

34
 
学习啦!!
此帖出自编程基础论坛
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

35
 
楼主是郭大虾么?好生厉害
此帖出自编程基础论坛
 
个人签名努力学习,好好生活
 
 

回复

1672

帖子

0

TA的资源

裸片初长成(初级)

36
 

郭大虾是谁?

我不姓郭
此帖出自编程基础论坛
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

37
 
很受教啊
此帖出自编程基础论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

38
 

回复 32楼 redstone9910 的帖子

学习了 !涨!!!
此帖出自编程基础论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

39
 

不错,谢谢楼主,正好碰到这样的问题

对我的问题很有指导意义。
我的问题如下:
ATMEL ARM MCU 的linux下面的程序,开始都可以调用printf()顺利打出来带有参数的字符串,比如printf("\n test string : %s\n",str); ,但是执行到后面,如果还要调用这个形式的printf("%s",str);%s可以换成%d %f等其他标识符,参数也没有少,但是程序就崩溃退出了。在崩溃退出之前,调用了一个有很大缓冲(比如100*1024)的类的对象的函数,是不是就是这个原因导致printf打印失效,导致程序异常退出呢?
此帖出自编程基础论坛
 
 
 

回复

1672

帖子

0

TA的资源

裸片初长成(初级)

40
 

回复 41楼 foxware 的帖子

不好说。另外,在函数里面开很大的局部变量,例如100*1024,在编程规范里面是不允许的。会导致堆栈写坏。我觉得这个可能性非常大。
我会专门写文章讲述这个问题。
此帖出自编程基础论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表