V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
dddd
V2EX  ›  程序员

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

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

    代码如下:

    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] = '#';
    

    为什么不报错?

    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   ·   993 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 72ms · UTC 19:31 · PVG 03:31 · LAX 12:31 · JFK 15:31
    ♥ Do have faith in what you're doing.