我有一个关于内存分配顺序的问题。 在下面的代码中,我在循环中分配4个字符串。 但是当我打印地址时,他们似乎并没有一个接一个地分配……我做错了什么,或者是OS实施的某种防御机制,以防止可能的缓冲区溢出? (我使用的是Windows Vista)。
谢谢。
char **stringArr; int size=4, i; stringArr=(char**)malloc(size*sizeof(char*)); for (i=0; i<size; i++) stringArr[i]=(char*)malloc(10*sizeof(char)); strcpy(stringArr[0], "abcdefgh"); strcpy(stringArr[1], "good-luck"); strcpy(stringArr[2], "mully"); strcpy(stringArr[3], "stam"); for (i=0; i<size; i++) { printf("%sn", stringArr[i]); printf("%d %unn", &(stringArr[i]), stringArr[i]); }
输出:
abcdefgh 9650064 9650128
祝你好运9650068 9638624
mully 9650072 9638680
stam 9650076 9638736
通常,当您通过malloc()
请求内存时,C运行时库会将请求的大小四舍五入到最小分配大小。 这可以确保:
但是,这些是实现细节,您无法真正依赖malloc()
任何特定行为。
但是当我打印地址时,它们似乎并不是一个接一个地分配的……
所以?
我做错了什么,或者是OS实施的某种防御机制,以防止可能的缓冲区溢出?
可能“不”。
只是出于兴趣,你会得到什么地址?
您不应该依赖malloc返回的任何特定顺序或值间距。 它以神秘和不可预测的方式表现。
通常,期望一系列按时间顺序的分配将导致某种程度上相关的内存地址是合理的,但正如其他人所指出的那样,它肯定不是堆管理器的要求。 但是,在这种特殊情况下,您可能会看到低碎片堆的结果 。 Windows保留了可以快速满足请求的小块内存列表。 这些可以是任何顺序。
您不能依赖malloc来为您提供连续的地址。 这完全取决于实现,可能是堆的当前状态; 一些实现可能,许多不会。
如果您需要地址是连续的,请分配一个大的内存块并设置指针以指向其中的不同区域。
正如其他人所提到的,没有标准来指定malloc()分配的内存块应该以哪种顺序位于内存中。 例如,释放的块可以分散在堆中,并且可以按任何顺序重复使用。
但即使这些块碰巧是一个接一个,它们很可能不会形成一个连续的块。 为了减少碎片,堆管理器仅分配特定大小的块,例如2的幂(64,128,256,512等字节)。 因此,如果为字符串保留10个字节,那么可能会有22或54个未使用的字节。
内存开销是除非真的有必要使用动态内存分配不是一个好主意的另一个原因。 使用静态数组更容易,更安全。
由于您对了解malloc()
返回的地址很有兴趣,因此应确保正确打印它们。 通过“正确”,我的意思是你应该使用printf()
的正确格式说明符来打印地址。 你为什么用"%u"
代表一个而"%d"
用于另一个?
您应该使用"%p"
来打印指针。 这也是你需要在C中使用强制转换的极少数情况之一:因为printf()
是一个可变函数,编译器不能告诉你作为参数传递给它的指针必须是void *
类型void *
或不。
此外,您不应该转换malloc()
的返回值。
修好了上述内容后,该计划是:
#include #include #include int main(void) { char **stringArr; int size=4, i; stringArr = malloc(size * sizeof *stringArr); for (i=0; i < size; i++) stringArr[i] = malloc(10 * sizeof *stringArr[i]); strcpy(stringArr[0], "abcdefgh"); strcpy(stringArr[1], "good-luck"); strcpy(stringArr[2], "mully"); strcpy(stringArr[3], "stam"); for (i=0; i
当我运行它时,我得到以下输出:
abcdefgh 0x100100080 0x1001000a0 good-luck 0x100100088 0x1001000b0 mully 0x100100090 0x1001000c0 stam 0x100100098 0x1001000d0
在我的计算机上, char **
指针长度为8个字节,因此&stringArr[i+1]
比&stringArr[i]
大8个字节。 这是由标准保证的:如果malloc()
有一些空间,那个空间是连续的。 你为4个指针分配了空间,这四个指针的地址彼此相邻。 您可以通过以下方式更清楚地看到:
printf("%dn", (int)(&stringArr[1] - &stringArr[0]));
这应该打印1。
关于随后的malloc()
,由于每个stringArr[i]
都是从单独的malloc()
,因此实现可以自由地为它们分配任何合适的地址。 在我的实现中,使用该特定运行,地址相隔0x10字节。
对于您的实现,似乎char **
指针长度为4个字节。
关于你的单个字符串的地址,它看起来像malloc()
正在进行某种随机化(允许这样做)。
以上就是c/c++开发分享C中的内存分配相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/560550.html