V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dddd
V2EX  ›  程序员

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

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

    代码如下:

    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   ·   实用小工具   ·   2669 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 05:20 · PVG 13:20 · LAX 21:20 · JFK 00:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.