为什么在 C 语言里面动态分配的空间被填满之后再加一个字符不算越界? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
dddd
V2EX    程序员

为什么在 C 语言里面动态分配的空间被填满之后再加一个字符不算越界?

  •  
  •   dddd 2015-06-15 15:00:36 +08:00 4418 次点击
    这是一个创建于 3775 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码如下:

    int i; char *result = (char*)malloc(3*sizeof(char)); memset(result, 0, 3*sizeof(char)); for (i = 0; i < 3; i++) { result[i] = 'a'; } result[index] = '#'; 

    为什么不报错?

    第 1 条附言    2015-06-15 17:59:30 +08:00
    int index = 3; 把代码扣出来的时候忘记改了……
    28 条回复    2015-06-16 09:01:38 +08:00
    Monad
        1
    Monad  
       2015-06-15 15:08:16 +08:00
    不报错从标准上来说应该是undefined behaviour
    从实际上来说 是因为ptmalloc2(或者其它memory allocator)会Round Up你malloc的大小,所以你写入的区域实际上是属已经向OS申请的内存区域,而不是OS禁止写入的区域(那样会segmentation fault)
    nicai000
        2
    nicai000  
       2015-06-15 15:09:19 +08:00
    算越界, 不检查不警告, 就这么设计的
    tabris17
        3
    tabris17  
       2015-06-15 15:12:11 +08:00
    C的数组是不安全的类型,所谓不安全的类型就是语言本身不会越界检查
    xylophone21
        4
    xylophone21  
       2015-06-15 15:12:23 +08:00
    因为这样可以写出
    char *result = (char*)0x12345678;
    这样的代码
    leavic
        5
    leavic  
       2015-06-15 15:14:56 +08:00
    底层语言变态的地方就是可以让你访问任意地址,而且很轻松
    xionghengheng
        6
    xionghengheng  
       2015-06-15 15:20:28 +08:00
    看看malloc的源码你就懂了,谁说堆内存malloc一次就是按照申请多少就给你多少,他可能会给你比你申请内存多一点,这都是内存的动态管理
    ChanneW
        7
    ChanneW  
       2015-06-15 15:28:13 +08:00
    再加多少都不算越界
    wy315700
        8
    wy315700  
       2015-06-15 15:30:30 +08:00
    还可以访问 result[-1]
    abscon
        9
    abscon  
       2015-06-15 15:46:43 +08:00
    说一句跑题的话:index 这个变量在哪里定义的?楼主你这段代码编译通过了吗?
    zmj1316
        10
    zmj1316  
       2015-06-15 16:27:51 +08:00 via Android
    @abscon 我以为就我一个呢 亏我还仔细找了。。。
    dddd
        11
    dddd  
    OP
       2015-06-15 17:34:54 +08:00
    @abscon 额…… index = 3
    yangff
        12
    yangff  
       2015-06-15 17:37:40 +08:00
    你可以操作任何一个属于你的地址.
    sleeperqp
        13
    sleeperqp  
       2015-06-15 17:47:47 +08:00
    不能说是任意地址 只能说是该程序的线性地址
    loveuqian
        14
    loveuqian  
       2015-06-15 17:49:41 +08:00 via iPhone
    因为越界不报错啊
    zhicheng
        15
    zhicheng  
       2015-06-15 17:55:04 +08:00
    谁丫的知道你 index 是啥值。
    icedx
        16
    icedx  
       2015-06-15 18:46:57 +08:00 via Android
    C 语言哪有越界一说
    想去哪就去哪
    21grams
        17
    21grams  
       2015-06-15 18:53:21 +08:00
    那你说说由谁来报这个错呢?
    zhangxiao
        18
    zhangxiao  
       2015-06-15 19:09:44 +08:00
    这就好比一条街上每隔10米一户人家,一共3户(0,1,2)。
    写个简单的机器人发,就告诉机器人在n*10的地方丢下包裹就好了。所以你硬要是发给#3,那就丢在了30米的地方,硬要发给#10,就丢在了100米的地方,机器人不管那里有没有住户。
    如果让楼主自己去发,你一看就会说,这条街上没有#3啊,就报错了
    thinkIn
        19
    thinkIn  
       2015-06-15 20:00:35 +08:00 via iPhone
    虽然越界不会报错,但一定不要做这种事,很可能会覆盖掉malloc与free维护的链表节点头信息,这将会是致命错误。
    zi
        20
    zi  
       2015-06-15 20:57:11 +08:00
    C语言的数组名其实是个指针来的,既然是指针,那就可以随便指随便写,至于你随便写之后覆盖掉什么东西。。后果自负。。
    mintist
        21
    mintist  
       2015-06-15 22:35:54 +08:00
    给你自由,自己把握
    way2exluren
        22
    way2exluren  
       2015-06-15 22:41:50 +08:00 via Android
    加句free(result );应该会崩溃
    yaoc
        23
    yaoc  
       2015-06-16 00:10:42 +08:00 via Android
    @way2exluren
    应该不会,因为result指向的还是一开始分配给它的内存
    way2exluren
        24
    way2exluren  
       2015-06-16 00:12:52 +08:00 via Android
    @yaoc 你去试试。。。。
    way2exluren
        25
    way2exluren  
       2015-06-16 00:14:36 +08:00 via Android
    @yaoc 分配好的内存前后都有几个自己是用来管理内存的。覆盖了以后,free再重新整理内存快的时候会出错。。
    yaoc
        26
    yaoc  
       2015-06-16 00:31:36 +08:00 via Android
    @way2exluren 我试了,没有什么问题
    alphonsez
        27
    alphonsez  
       2015-06-16 01:43:22 +08:00
    试试看多越界一点,估计就出问题了。这种问题会藏的很深,到时候真崩溃了很难找。一个字节的这种,搞不好还能来个heartbleed.
    Heartwork
        28
    Heartwork  
       2015-06-16 09:01:38 +08:00 via Android
    1 因为malloc在分配的内存是16字节补齐的。所以就算你访问了后面的几个字节,也还是在有效内存范围内。

    2 即使你访问了多于16字节的非法空间,还是需要根据brk或sbrk查看数据段末端的地址,如果超过这个值,就会有内存访问异常了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5414 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 06:03 PVG 14:03 LAX 23:03 JFK 02:03
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86