我使用两个变量,其中内存是动态分配的,我打印内存位置,但它们不是连续的.为什么?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a = malloc(sizeof(int));
int *b = malloc(sizeof(int));
printf("\n a=%p \t b=%p \n",a,b);
}
Run Code Online (Sandbox Code Playgroud)
我得到的答案(在Linux中)是
第一次:
a=0x20a0010 b=0x20a0030
Run Code Online (Sandbox Code Playgroud)
第二次:
a=0x657010 b=0x657030
Run Code Online (Sandbox Code Playgroud)
第3次:
a=0x139e010 b=0x139e030
Run Code Online (Sandbox Code Playgroud)
为什么第1次,第2次和第3次的内存位置a和b变量之间的确切差异是什么?
这与分页内存有关吗?
我的处理器是64位.
两个连续分配之间的差距与分页无关.您的分配非常小,以至于它们位于数据段中.libc的内部处理这些-你以外的空间sizeof int字节通常包含指向前一个和下一个数据块分配的大小-毕竟free只会得到一个指针,它需要弄清楚它是多少内存解除分配.
另外,这两个指针都与16字节边界对齐.C11 7.22.3说
指针返回如果分配成功,则适当地对准,使得其可以被分配给一个指针到任何类型的对象与基本对齐要求,然后用于访问这样的对象或在分配的空间这样的对象的阵列(直到空间被明确释放).
因此,即使您将它们用于intC标准,也要求返回的指针对应于任何数据类型 - 在您的实现上是16字节.
但是,如果你分配一个非常大的对象,glibc将使用mmap相反的方式映射整个页面.然后对齐(在我的64位计算机上)恰好是从4K页面开始的16个字节:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a = malloc(12345678);
int *b = malloc(12345678);
printf("\n a=%p \t b=%p \n",a,b);
}
Run Code Online (Sandbox Code Playgroud)
什么时候跑
% ./a.out
a=0x7fb65e7b7010 b=0x7fb65dbf0010
Run Code Online (Sandbox Code Playgroud)
人们可以看到mmap呼叫strace ./a.out- 有其他系统呼叫
mmap(NULL, 12349440, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb65e7b7000
mmap(NULL, 12349440, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb65dbf0000
Run Code Online (Sandbox Code Playgroud)
至于为什么地址不断变化,从一个执行到另一个-这是由于地址空间布局随机化,或ASLR -一种安全机制,这使得它更难邪恶饼干可以预见利用不确定的行为在你的代码.
PS如果您确实需要int在连续地址处动态分配空间2 秒,请分配一个数组.
操作系统处理内存分配,并且在动态分配两个连续变量时不能保证该内存是连续的。我还应该提到,这是称为ASLR的防御机制的结果。ASLR 通过在执行过程中随机化进程的位置来防御缓冲区溢出,这可能包括堆栈、堆和库。这就是您注意到这些地址发生变化的原因。按照标准,您只能得到以下保证。
ISO C11 7.22.3.4 Malloc
1)概要
#include <stdlib.h>
void* malloc(size_t size);
Run Code Online (Sandbox Code Playgroud)
2)描述 malloc 函数为大小由 size 指定且值不确定的对象分配空间。
3)返回 malloc 函数返回空指针或指向已分配空间的指针。
| 归档时间: |
|
| 查看次数: |
508 次 |
| 最近记录: |