请教一个非常简单的 c 语言内存申请问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
zhangjinghua
V2EX    程序员

请教一个非常简单的 c 语言内存申请问题

  •  
  •   zhangjinghua 2022-01-04 21:14:41 +08:00 2356 次点击
    这是一个创建于 1377 天前的主题,其中的信息可能已经有所发展或是发生改变。
    https://s4.ax1x.com/2022/01/04/TOB5oq.png
    为啥么会这样报错呢,看不懂了(不会发图,希望大佬教一下)
    23 条回复    2022-01-04 23:08:41 +08:00
    zhangjinghua
        1
    zhangjinghua  
    OP
       2022-01-04 21:18:08 +08:00
    嗡嗡嗡,求回复
    dlsflh
        2
    dlsflh  
       2022-01-04 21:26:09 +08:00 via Android
    不懂
    TaylorJack123
        3
    TaylorJack123  
       2022-01-04 21:42:21 +08:00 via iPhone
    memset 时,把变量 c 强制转成 unsigned char*。c 是 int 型指针,你如果对 8 个单位清零,应该是越界了^_^
    msg7086
        4
    msg7086  
       2022-01-04 21:51:46 +08:00 via Android
    一眼没看出问题,但是 memset 是不是应该在 if 里面才对?(虽然这不是引发问题的原因。)
    zhangjinghua
        5
    zhangjinghua  
    OP
       2022-01-04 21:53:45 +08:00
    破案了,我觉得应该不是越界了
    没有强转啊

    #include <stdlib.h>

    加了这个好了,但是我仍然不知道为什么
    basncy
        6
    basncy  
       2022-01-04 21:55:16 +08:00
    static int *c = NULL;

    笔试的时候别说是我教的.
    iOCZ
        7
    iOCZ  
       2022-01-04 21:59:45 +08:00
    代码没啥问题。。。所以,应该是别的问题
    xiri
        8
    xiri  
       2022-01-04 21:59:59 +08:00
    @zhangjinghua
    malloc 函数在 stdlib.h 里面,memset 函数在 string.h 里面,printf 在 stdio.h 里面,正常来说你需要把这三个头文件都加上。我刚刚还特地试了下,gcc 9.3.0 下可以正常编译和运行,没有任何问题,但是不加头文件的话会弹警告(实际上就是默认给加上了)。
    Tanix2
        9
    Tanix2  
       2022-01-04 22:01:51 +08:00
    @zhangjinghua 按理说没有 stdlib.h 用不了 malloc
    iOCZ
        10
    iOCZ  
       2022-01-04 22:04:17 +08:00
    试试没有 include 的情况下,能不能从 IDE 跳过去。。。。
    ipwx
        11
    ipwx  
       2022-01-04 22:05:51 +08:00
    When the application is linked with a debug version of the C run-time libraries, malloc resolves to _malloc_dbg

    https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/malloc?view=msvc-170

    盲猜没引入 stdlib.h 所以没解析到 _malloc_dbg ,隐式连接了正统 malloc ,然后调试器跪了
    zhangjinghua
        12
    zhangjinghua  
    OP
       2022-01-04 22:06:06 +08:00
    @xiri 正解正解
    话题终结
    zhangjinghua
        13
    zhangjinghua  
    OP
       2022-01-04 22:07:10 +08:00
    好丢人啊,这么低级的错误
    (确实好久没用这个函数了,公司不让用,有其他的函数申请内存)
    Origami404
        14
    Origami404  
       2022-01-04 22:12:45 +08:00 via Android   2
    @zhangjinghua 因为如果你不引入 malloc 的声明的话,按照 k&r c 的遗留标准,这个函数会被声明为 int (*)(), 于是在 64 位平台上 malloc 的返回值,那个指针,有可能被截断为一个 int ,导致你 c 指向的地方不对了。这也就是为什么 modern c 里推荐不要强转 malloc 返回值,以检测到这类错误

    不大确定,希望多加指正
    Origami404
        15
    Origami404  
       2022-01-04 22:15:52 +08:00 via Android
    当然我觉得理论上现代编译器应该能检测到这种问题,尤其是对这么常见的函数,所以我觉得 @ipwx 老哥的解释也很有可能,这可能需要看看编译出的汇编是怎么样的才能决定了(当然两个原因有可能一起发生也说不定)
    wevsty
        16
    wevsty  
       2022-01-04 22:16:52 +08:00
    最新的 MSVC 其实有弹警告,你可能没注意到。

    warning C4013: “malloc”未定义;假设外部返回 int

    根据提示我猜测:
    编译器没找到 malloc 的定义,然后默认返回的 int* 为 int 。
    然后链接器是正常 link 到了 malloc 上,在 32 位下面这样是没问题的,但如果编译 64 位的程序返回的 int* 本来是占 8 字节但是编译器强行截断成了 4 字节的 int 在赋值给 int* 所以地址就不对了。
    wevsty
        17
    wevsty  
       2022-01-04 22:18:48 +08:00
    我自己实测结果:VS2022
    编译位 X86 不加 stdlib.h 运行调试都没问题
    如果编译为 X64 不加的情况下调试就会弹错误了。
    zhangjinghua
        18
    zhangjinghua  
    OP
       2022-01-04 22:22:22 +08:00
    #include <stdio.h>
    #include <stdlib.h>

    int* a = NULL;

    int* b()
    {
    int c[2] = { 0 };
    if (c != NULL)
    {
    c[0] = 123;
    c[1] = 456;
    }
    return c;
    }

    int main()
    {

    a = b();
    printf("a[0] : %d \n", a[0]);
    printf("a[1] : %d \n", a[1]);
    printf("Hello World!\n");
    }

    结果 :
    a[0] : 123
    a[1] : 0
    Hello World!

    #include <stdio.h>
    #include <stdlib.h>

    int* a = NULL;

    int* b()
    {
    static int c[2] = { 0 };
    /////////这里加了 static
    if (c != NULL)
    {
    c[0] = 123;
    c[1] = 456;
    }
    return c;
    }

    int main()
    {

    a = b();
    printf("a[0] : %d \n", a[0]);
    printf("a[1] : %d \n", a[1]);
    printf("Hello World!\n");
    }

    结果
    a[0] : 123
    a[1] : 456
    Hello World!

    这里为啥会这样呢??? 虽然我知道和变量生命周期有关,但是为什么会留一半呢???
    zhangjinghua
        19
    zhangjinghua  
    OP
       2022-01-04 22:22:53 +08:00
    @wevsty 厉害啊,老哥,原来还有这样一说
    Origami404
        20
    Origami404  
       2022-01-04 22:23:46 +08:00 via Android
    @zhangjinghua 是 ub ,第一个程序理论上可以出现任何行为,包括让你电脑爆炸
    wevsty
        21
    wevsty  
       2022-01-04 22:24:15 +08:00
    @zhangjinghua
    未定义行为的结果就不要纠结了。
    iOCZ
        22
    iOCZ  
       2022-01-04 22:39:44 +08:00
    莫非是嵌入式的?不让用标准库
    msg7086
        23
    msg7086  
       2022-01-04 23:08:41 +08:00 via Android
    看代码的时候确实看到 include 段太短,猜到了没引入头文件,但没猜到默认返回类型太短截断指针的问题。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     6064 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 02:30 PVG 10:30 LAX 19:30 JFK 22:30
    Do have faith in what you're doing.
    ubao 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