• 请不要在回答技术问题时复制粘贴 AI 生成的内容
dddd
V2EX  ›  程序员

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

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

    2 即使你访问了多于16字节的非法空间,还是需要根据brk或sbrk查看数据段末端的地址,如果超过这个值,就会有内存访问异常了。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2487 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 68ms · UTC 00:55 · PVG 08:55 · LAX 16:55 · JFK 19:55
    ♥ Do have faith in what you're doing.