免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4032 | 回复: 17
打印 上一主题 下一主题

新手学C指针的疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-04-21 22:37 |只看该作者 |倒序浏览
本帖最后由 tioover 于 2012-04-21 22:46 编辑

定义一个有两个元素的数组,用指针指向最后一个元素,再加一

  1. int main()
  2. {
  3.     int a[2];
  4.     a[0] = 42;
  5.     a[1] = 42;
  6.     printf("%d", *(&a[1] + 1));
  7. }
复制代码
输出0,而不是段错误,为什么?

而且

  1. int main()
  2. {
  3.     int a[2];
  4.     a[0] = 42;
  5.     a[1] = 42;
  6.     *(&a[2] + 1) = 'a';
  7.     printf("%c", *(&a[1] + 1));
  8. }
复制代码
会输出a

我用malloc分配了200个int的空间

int *a = malloc(200 * sizeof(int));

也有一样的效果,超过了分配的空间还可以正常的操作,而且没有类型的限制……

论坛徽章:
12
巳蛇
日期:2013-09-16 15:32:242015年辞旧岁徽章
日期:2015-03-03 16:54:152015年亚洲杯之约旦
日期:2015-02-11 14:38:37双鱼座
日期:2015-01-05 11:05:47戌狗
日期:2014-12-08 09:41:18戌狗
日期:2014-08-15 09:29:29双子座
日期:2014-08-05 09:17:17卯兔
日期:2014-06-08 15:32:18巳蛇
日期:2014-01-27 08:47:08白羊座
日期:2013-11-28 21:04:15巨蟹座
日期:2013-11-13 21:58:012015年亚洲杯之科威特
日期:2015-04-17 16:51:51
2 [报告]
发表于 2012-04-21 22:51 |只看该作者
tioover 发表于 2012-04-21 22:37
定义一个有两个元素的数组,用指针指向最后一个元素,再加一输出0,而不是段错误,为什么?

而且会输出a ...


C/C++编译器生成的代码不会检查你对内存的访问是否越界,所以并不是越界了就一定会发生段错误。
由访存导致的段错误的可能原因(不全):读写的内存地址不存在/无权限;越界访存错误的修改了栈,导致函数返回时跳转到不存在/不可执行的地址。

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
3 [报告]
发表于 2012-04-21 22:56 |只看该作者
什么叫未定义行为,就是根本没考虑(无论是忘了考虑,还是不屑于考虑)这一点
如果规定了这种行为一定要段错误,那叫已定义行为

另外,简单的a[2]不写,你写*(&a[1] + 1)是出于什么考量?

论坛徽章:
0
4 [报告]
发表于 2012-04-21 23:02 |只看该作者
bruceteen 发表于 2012-04-21 22:56
什么叫未定义行为,就是根本没考虑(无论是忘了考虑,还是不屑于考虑)这一点
如果规定了这种行为一定要段 ...

只是一个例子……主要是用malloc分配了20个字符长度的地址,结果发现输入可以超过20个
  1. #include<stdio.h>
  2. #include <stdlib.h>

  3. int main()
  4. {
  5.     char *a = malloc(20 * sizeof(char));
  6.     scanf("%s", a);
  7.     printf("%s", a);
  8. }
复制代码
输入“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa”

输出和输入一样

------------------
现在大致上明白了
谢谢

论坛徽章:
0
5 [报告]
发表于 2012-04-21 23:15 |只看该作者
本帖最后由 walleeee 于 2012-04-21 23:54 编辑

我来回答你。

1.
一般是向低地址生长,换句话说,就是比如
16    a+0   42
12    a+1   42
8      a+2   'a'
其中假设int是4字节,char是1字节。
于是就有这个布局,于是就有你看到的现象。
你后面用堆内存,原理一样,你自己想想。

2.
malloc可能会给你多分配一些内存,并非你传入20就是20,可能会有对齐,比如到32等等。
还有一个非对齐因素就是malloc可能会给你一个优惠,比如glibc就有优惠。
再有,你这里程序之所以还能正常输出,我描述如下,你不能明白就算了,只是代码不要这样做
你malloc出一个20空间,然后a指针来引用这个空间,你scanf在写这个空间,你写多了,溢出了,但是你并没有后续的内存malloc/free,尽管你可能已经破坏了分配器的数据结构,所以你这个看起来溢出了也没问题。
但是你试试a分配成栈上的,比如
a[20],然后来溢出。这个时候你就懂了。
甚至这里你还可以研究直接溢出来覆盖地址,达到某些目的

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
6 [报告]
发表于 2012-04-21 23:16 |只看该作者
有两点
1。你用malloc请求分配20个字节,而不是要求只允许分配20字节,所以库函数即使分配给你250个字节也是符合要求的。在这种情况下,根本不会有任何错误
2。即使你覆写到实际分配的内存外,但此错误未能引起系统的反应,你也看不出是否有错误

第一种情况,windows下用_msize可以得到实际分配的内存,linux下也有相应函数,上次我还贴过,忘了名字了。你可以越出这个界限写个数据试试看
第二种情况就没法了,我上个月刚花了5天查出了一个类似的bug:由于递归过多,导致偶尔会在一个函数中报错,我在这个函数中查呀查,把这个函数重写了好几遍,都无效,最后才发现问题在其它地方

论坛徽章:
0
7 [报告]
发表于 2012-04-21 23:22 |只看该作者
回复 6# bruceteen


    不用你说的这么复杂。他溢出一次malloc后再malloc一次就知道了

论坛徽章:
0
8 [报告]
发表于 2012-04-21 23:25 |只看该作者
walleeee 发表于 2012-04-21 23:15
我来回答你。

1.


谢谢,溢出以后我试试free结果报错,应该就是你说的原因

论坛徽章:
0
9 [报告]
发表于 2012-04-21 23:37 |只看该作者
回复 8# tioover


不是应该,这是必然。当然,这也要看分配器具体用什么算法,手段不一样而已

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
10 [报告]
发表于 2012-04-21 23:43 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP