| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 528 人关注过本帖
标题:诡异又霸道的strcpy()
只看楼主 加入收藏
pedone_c
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2011-7-26
结帖率:100%
收藏
已结贴  问题点数:20 回复次数:9 
诡异又霸道的strcpy()
大家都知道,为指针分配内存时,如果内存分配大小不够时,就会导致出现越界的错误。但是我一天在使用用字符串复制函数strcpy(dst,src)时,误用了sizeof(src)作为大小来给*dst分配空间,但是有编译和运行的时候均没有报错,再继续调试更是发现更加诡异的事……这里先的程序贴上来(注:我是用GCC进行编译的):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    char *src="abcdefgh";
    char *dst=NULL;

    printf("sizeof(src)=%d\n",sizeof(src));
    dst=(char *)malloc(sizeof(src));
    strcpy(dst,src);
    printf("dst_add=%x\tdst:%s\n",dst,dst);
   
    src=NULL;
    dst=NULL;

}

打印出来的结果:
Sizeof(src)=4
Dst_add=8d87008    dst:abcdefgh

第一个诡异的事出来了:由sizeof(src)=4知道给dst所指地址分配了4个这节,而src中字符长度为9个字节,显然内存大小不够,但程序不但没有报错,而且自行延拓了空间。

下面再把程序修改一下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    char *src="abcdefgh";
    char *dst=NULL;
    char *dst2=NULL;

    printf("sizeof(src)=%d\n",sizeof(src));
    dst=(char *)malloc(sizeof(src));
    dst2=(char *)(dst+4);
    printf("dst_add=%x\tdst2_add=%x\n",dst,dst2);
    strcpy(dst2,"pedone");
    printf("dst2:%s\n",dst2);
    strcpy(dst,src);
    printf("src_add=%x\n",src);
    printf("dst_add=%x\tdst:%s\n",dst,dst);
    printf("dst2_add=%x\tdst2:%s\n",dst2,dst2);

    src=NULL;
    dst=NULL;
    dst2=NULL;

}

打印出来的结果:
Sizeof(src)=4
Dst_add=932e008 dst2_add=932e00c
//此处说明dst2 所指地址确实是在dst的基础上加4个字节
Dst2:pedone    //说明dst2所指地址中确实已复制时字符串"pedone"
Src_add=8048634  //用来说明dst和dst2并非指向src所指地址
Dst_add=932e008  dst:abcdefgh
Dst2_add=932e00c  dst2:efgh


第二个诡异的事也出来了:从上面的结果可以看出,在dst2所指地址,也就是dst所指地址加上4个字节的地址处,放入字符串“pedone”,它显然占据了要将“abcdefgh\0”这9个字符放入dst所地址后面的内存空间。大家看,再将"abcdefgh\0"这个字符串复制到dst所指地址后,鸠占鹊巢啊!!它硬是活生生的把str2所指地址中的内容踢走了,而且还把别人改名换姓了,把str2地址内容变成str1的了,真的不得不感叹strcpy()你太霸道了啊!!

高手说说为何strcpy()如此的霸道……求解!~
搜索更多相关主题的帖子: 内存 include 字符串 
2011-07-26 23:40
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
唉,我都不好解释了,强烈建议LZ多去看看书,有太多知识你没懂。。。

My life is brilliant
2011-07-26 23:49
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
正确啊,C的机制就是这样的。

授人以渔,不授人以鱼。
2011-07-26 23:50
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
回复 3楼 TonyDeng
。。。。。。。。。

My life is brilliant
2011-07-26 23:53
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
当然正确,不这样就是他的编译器有问题,哈哈~
后面推出的VC6、VS系列,都有个叫“安全字符串函数”的概念,你以为那是没事找事的?真以为C++仅仅是加强版的C语言那么简单?

授人以渔,不授人以鱼。
2011-07-26 23:56
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
回复 5楼 TonyDeng
第一个问题:malloc在堆中分配内存一块大小为4字节的内存,由于你写入了10个字符,所以占用了你没有权限使用的后6个字节的内存,后果不明确,有可能把某个程序的数据覆盖了,运气好可能这块内存没有使用过。

第二个问题:和第一个问题一样,使用了不应该使用的空间,这样就算了,程序最后为什么不调用free(),而直接把指针置NULL?

My life is brilliant
2011-07-27 00:08
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:20 
6楼的话跟楼主说吧。有没有权限是你以为的,C语言就不会理会你这种自以为的权限,这也正是它的指针操作给人方便的好处所带来的祸患,根本原因在于它的字符串机制是在最后以0结束的,只要没遇到0,它就会一直循环写下去,指针闭着眼睛++往前移,字符就一路填下去,一直填到0为止,才不管后面是什么东西占用着,照覆盖了。现代安全字符串函数,全部都要传递字符计数器参数,明确表示写入多少字符,不以0为标准(unicode字符串很多字符就含有0,典型如拉丁字母字符),还有一种是带截断功能的,不够空间会自动截断,不会继续写下去(即不会发生楼主这种事)。避免的唯一办法是写程序的人多设置检查机制,这与语言无关,是写程序的人的习惯问题,C的这种机制很正常,人家早就说明是这样运作的,写程序的人自己不注意,不要怪C,它很忠实地按C的标准实施了。

C不霸道,写程序的人霸道而已。C的高效,是在这种无遮拦的方便性之下实现的,一旦把各种检查机制设置完善,它的效率与其它语言相差无几。不要以为学C(类C语言)的高人一等,视其它语言如无物,须知别的语言绝对不会出现这种现象,因为人家事先防范了这些漏洞,把代码和时间花在了这方面,而我们所看到的C高效,是牺牲了这些东西换取来的。

释放空间与否,那在这里算是小问题,不是主要问题。

授人以渔,不授人以鱼。
2011-07-27 00:23
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
回复 7楼 TonyDeng
我想说的是,在堆中有很大块空的内存块,所以LZ能正常运行也很常见,如果要覆盖别人的数据时,由于我们程序的权限不够,那么就会出现一个对话框 提示 “该内存不能为 'written',程序将不能再运行下去,调用malloc之后调用free应该和吃饭后要洗碗是对应的,当然你也可以不洗。

My life is brilliant
2011-07-27 00:54
vfdff
Rank: 6Rank: 6
等 级:侠之大者
威 望:8
帖 子:2172
专家分:425
注 册:2005-7-15
收藏
得分:0 
用release方式编译可能就不行了!

~~~~~~~~~~~~~~~好好学习~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2011-07-27 00:59
pedone_c
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2011-7-26
收藏
得分:0 
谢谢大家 作为一个初学者 在这里学习了……
2011-07-27 08:54
快速回复:诡异又霸道的strcpy()
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.016646 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved