首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >malloc()的有趣行为

malloc()的有趣行为
EN

Stack Overflow用户
提问于 2016-09-29 21:13:41
回答 4查看 142关注 0票数 0

这是我为GCC编译器编写的代码。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int *p;
    p = (int *)malloc(9 * sizeof(char));
    p[0] = 2147483647;
    p[1] = 2147483647;
    p[2] = 1025;
    printf("%d, %d, %d, %d\n", sizeof(char), *(p), *(p+1), *(p+2));
}

输出如下:

代码语言:javascript
复制
1, 2147483647, 2147483647, 1025

我的问题是,虽然我只给指针分配了9个字节,但它似乎使用了所有的12个字节。如果我转换为(char *)而不是(int *),结果是相同的(除了编译器警告)。malloc()的分配是不是全周期的?也就是说,它总是以指针的数据类型的倍数进行分配,而不管我们分配了什么?或者它是特定于实现的?

EN

回答 4

Stack Overflow用户

发布于 2016-09-29 21:17:05

代码语言:javascript
复制
    p = (int *)malloc(9 * sizeof(char));

如果整数的大小是4字节,那么你所做的就是undefined behavior。因为您分配了9个字节,使用了12个字节。

强制转换没有任何效果,实际上你根本不应该在C中强制转换malloc的结果。

触发未定义行为的另一个地方是对sizeof使用了错误的格式说明符,您应该在printf中使用%zu而不是%d (对于sizeof)。

票数 7
EN

Stack Overflow用户

发布于 2016-09-29 21:24:56

正如其他人所提到的,您正在写入的内容超出了错误分配的缓冲区的末尾。这将调用undefined behavior

未定义的行为意味着任何事情都可能发生。程序可能会崩溃,可能会产生意想不到的结果,或者(在这种情况下)它看起来工作正常。

进行看似不相关的代码更改可能会使您的程序突然开始崩溃。

为了说明发生了什么,下面是在valgrind下运行程序的输出:

代码语言:javascript
复制
[dbush] valgrind /tmp/x1
==19430== Memcheck, a memory error detector
==19430== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==19430== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==19430== Command: /tmp/x1
==19430==
==19430== Invalid write of size 4
==19430==    at 0x40050E: main (x1.c:11)
==19430==  Address 0x4c18048 is 8 bytes inside a block of size 9 alloc'd
==19430==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==19430==    by 0x4004E9: main (x1.c:8)
==19430==
==19430== Invalid read of size 4
==19430==    at 0x40051C: main (x1.c:12)
==19430==  Address 0x4c18048 is 8 bytes inside a block of size 9 alloc'd
==19430==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==19430==    by 0x4004E9: main (x1.c:8)
==19430==
1, 2147483647, 2147483647, 1025
==19430==
==19430== HEAP SUMMARY:
==19430==     in use at exit: 9 bytes in 1 blocks
==19430==   total heap usage: 1 allocs, 0 frees, 9 bytes allocated
==19430==
==19430== LEAK SUMMARY:
==19430==    definitely lost: 9 bytes in 1 blocks
==19430==    indirectly lost: 0 bytes in 0 blocks
==19430==      possibly lost: 0 bytes in 0 blocks
==19430==    still reachable: 0 bytes in 0 blocks
==19430==         suppressed: 0 bytes in 0 blocks
==19430== Rerun with --leak-check=full to see details of leaked memory
==19430==
==19430== For counts of detected and suppressed errors, rerun with: -v
==19430== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)

您可以从该输出中看到,您正在读取和写入已分配的缓冲区的末尾。

票数 3
EN

Stack Overflow用户

发布于 2016-09-29 21:18:06

您能够写入“额外”字节的事实并不意味着它们是分配给您的;它只是意味着它们存在。您没有理由期望这些字节在将来不会“神奇地”更改,因为您没有分配它们,如果其他代码分配了它们,可能会更改它们(并且,与您的代码不同,这样做是合法的)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39771340

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档