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

2022-01-04 21:14:41 +08:00
 zhangjinghua
https://s4.ax1x.com/2022/01/04/TOB5oq.png
为啥么会这样报错呢,看不懂了(不会发图,希望大佬教一下)
1994 次点击
所在节点    程序员
23 条回复
zhangjinghua
2022-01-04 21:18:08 +08:00
嗡嗡嗡,求回复
dlsflh
2022-01-04 21:26:09 +08:00
不懂
TaylorJack123
2022-01-04 21:42:21 +08:00
memset 时,把变量 c 强制转成 unsigned char*。c 是 int 型指针,你如果对 8 个单位清零,应该是越界了^_^
msg7086
2022-01-04 21:51:46 +08:00
一眼没看出问题,但是 memset 是不是应该在 if 里面才对?(虽然这不是引发问题的原因。)
zhangjinghua
2022-01-04 21:53:45 +08:00
破案了,我觉得应该不是越界了
没有强转啊

#include <stdlib.h>

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

笔试的时候别说是我教的.
iOCZ
2022-01-04 21:59:45 +08:00
代码没啥问题。。。所以,应该是别的问题
xiri
2022-01-04 21:59:59 +08:00
@zhangjinghua
malloc 函数在 stdlib.h 里面,memset 函数在 string.h 里面,printf 在 stdio.h 里面,正常来说你需要把这三个头文件都加上。我刚刚还特地试了下,gcc 9.3.0 下可以正常编译和运行,没有任何问题,但是不加头文件的话会弹警告(实际上就是默认给加上了)。
Tanix2
2022-01-04 22:01:51 +08:00
@zhangjinghua 按理说没有 stdlib.h 用不了 malloc
iOCZ
2022-01-04 22:04:17 +08:00
试试没有 include 的情况下,能不能从 IDE 跳过去。。。。
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
2022-01-04 22:06:06 +08:00
@xiri 正解正解
话题终结
zhangjinghua
2022-01-04 22:07:10 +08:00
好丢人啊,这么低级的错误
(确实好久没用这个函数了,公司不让用,有其他的函数申请内存)
Origami404
2022-01-04 22:12:45 +08:00
@zhangjinghua 因为如果你不引入 malloc 的声明的话,按照 k&r c 的遗留标准,这个函数会被声明为 int (*)(), 于是在 64 位平台上 malloc 的返回值,那个指针,有可能被截断为一个 int ,导致你 c 指向的地方不对了。这也就是为什么 modern c 里推荐不要强转 malloc 返回值,以检测到这类错误

不大确定,希望多加指正
Origami404
2022-01-04 22:15:52 +08:00
当然我觉得理论上现代编译器应该能检测到这种问题,尤其是对这么常见的函数,所以我觉得 @ipwx 老哥的解释也很有可能,这可能需要看看编译出的汇编是怎么样的才能决定了(当然两个原因有可能一起发生也说不定)
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
2022-01-04 22:18:48 +08:00
我自己实测结果:VS2022
编译位 X86 不加 stdlib.h 运行调试都没问题
如果编译为 X64 不加的情况下调试就会弹错误了。
zhangjinghua
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
2022-01-04 22:22:53 +08:00
@wevsty 厉害啊,老哥,原来还有这样一说
Origami404
2022-01-04 22:23:46 +08:00
@zhangjinghua 是 ub ,第一个程序理论上可以出现任何行为,包括让你电脑爆炸

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/826198

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX