为什么在 C 语言里面动态分配的空间被填满之后再加一个字符不算越界? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
请不要在回答技术问题时复制粘贴 AI 生成的内容
dddd

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

  •  
  •   dddd Jun 15, 2015 4878 views
    This topic created in 3971 days ago, the information mentioned may be changed or developed.

    代码如下:

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

    为什么不报错?

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

    2 即使你访问了多于16字节的非法空间,还是需要根据brk或sbrk查看数据段末端的地址,如果超过这个值,就会有内存访问异常了。
    About     Help     Advertise     Blog     API     FAQ     Solana     2988 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 135ms UTC 14:53 PVG 22:53 LAX 07:53 JFK 10:53
    Do have faithin 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