这是我为GCC编译器编写的代码。
#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));
}输出如下:
1, 2147483647, 2147483647, 1025我的问题是,虽然我只给指针分配了9个字节,但它似乎使用了所有的12个字节。如果我转换为(char *)而不是(int *),结果是相同的(除了编译器警告)。malloc()的分配是不是全周期的?也就是说,它总是以指针的数据类型的倍数进行分配,而不管我们分配了什么?或者它是特定于实现的?
发布于 2016-09-29 21:17:05
p = (int *)malloc(9 * sizeof(char));如果整数的大小是4字节,那么你所做的就是undefined behavior。因为您分配了9个字节,使用了12个字节。
强制转换没有任何效果,实际上你根本不应该在C中强制转换malloc的结果。
触发未定义行为的另一个地方是对sizeof使用了错误的格式说明符,您应该在printf中使用%zu而不是%d (对于sizeof)。
发布于 2016-09-29 21:24:56
正如其他人所提到的,您正在写入的内容超出了错误分配的缓冲区的末尾。这将调用undefined behavior。
未定义的行为意味着任何事情都可能发生。程序可能会崩溃,可能会产生意想不到的结果,或者(在这种情况下)它看起来工作正常。
进行看似不相关的代码更改可能会使您的程序突然开始崩溃。
为了说明发生了什么,下面是在valgrind下运行程序的输出:
[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)您可以从该输出中看到,您正在读取和写入已分配的缓冲区的末尾。
发布于 2016-09-29 21:18:06
您能够写入“额外”字节的事实并不意味着它们是分配给您的;它只是意味着它们存在。您没有理由期望这些字节在将来不会“神奇地”更改,因为您没有分配它们,如果其他代码分配了它们,可能会更改它们(并且,与您的代码不同,这样做是合法的)。
https://stackoverflow.com/questions/39771340
复制相似问题