为什么动态分配的两个变量的内存位置不连续?
我使用两个变量,其中动态分配内存,并打印内存位置,但它们不是连续的。为什么?为什么动态分配的两个变量的内存位置不连续?
#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);
}
我得到(在Linux中)是答案
第1次:
a=0x20a0010 b=0x20a0030
第2次:
a=0x657010 b=0x657030
第3次:
a=0x139e010 b=0x139e030
为什么a
和b
的存储位置之间的确切区别是第一,第二和第三次变量的方式?
这与寻呼记忆有关吗?
我的处理器是64位。
操作系统处理内存分配,并且不能保证在动态分配两个连续变量时该内存是连续的。我还应该提到,这是一种称为ASLR的防御机制的结果。 ASLR通过在执行过程中随机化一个进程的位置来防止缓冲区溢出,这可能包括stack, heap, and libraries。这就是为什么你注意到这些地址在变化。按照这个标准,你只能保证以下。
ISO C11 7.22.3.4 malloc的
1)概要
#include <stdlib.h>
void* malloc(size_t size);
2)说明 malloc函数为一个对象,其大小被指定分配空间按规模和价值是不确定的。
3)返回 malloc函数返回空指针或指向已分配空间的指针。
谢谢@Miket –
*“操作系统处理内存分配”* - 不一定是真的。一旦获得内存,运行时可以提供分配,前提是内存以前是空闲的。另请参阅[请问malloc实现是否将释放内存返回给系统?](https://stackoverflow.com/q/2215259/608639) – jww
如果你想连续的内存分配内存和unique_ptr与两个数组的大小,并指向你的指针的末尾和指针的中心,你从独特的指针得到。只记得不要删除你的a和b指针。
std::unique_ptr<int> a(new int[na+nb])
int * aptr = a.get();
Int * bptr = a.get() + na;
两个连续分配之间的差距与寻呼无关。您的分配太小以至于它们驻留在数据段中。 Libc在内部处理这些内容 - sizeof int
字节之外的空间通常包含指向前一个和下一个数据块的指针以及分配的大小 - 毕竟free
只会得到一个指针,并且需要计算出它有多少内存解除分配。
此外这两个指针都对齐到16字节的边界。 C11 7.22.3说
指针返回如果分配成功,则适当地对准,使得其可被指派给的指针的任何类型的物体,其一个基本对齐要求然后用于访问这样的对象或分配空间中的这样的对象的数组(直到空间被明确地解除分配)。
因此,即使你使用它们int
C标准要求指针返回任何数据类型保持一致 - 这对你的代码是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);
}
运行
% ./a.out
a=0x7fb65e7b7010 b=0x7fb65dbf0010
一个时可以看到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
至于为什么地址不断变化从一个执行到另一个 - 这是由于address space layout randomization, or ASLR - 一个安全机制,这使得它更难以在您的代码中使用利用未定义的行为。
P.S.如果您确实需要为连续地址动态分配空间,请分配一个数组。
那么为什么指针值每次都不相同? – EJP
@EJP补充说也是 –
谢谢@ antti haapala ..但是我不希望那个记忆是连续的..为什么它不是连续的是我的问题..以及我第一次提到我的记忆位置,第二次和第三次我的程序执行..如果你观察到的位置和差异b/w的内存位置alloctaed ..如果发现有些模棱两可... –
需要注意的是位于该块结束后的内存可能 在使用别的东西;也许一个块已经被 分配给malloc的另一个调用。
这实际上意味着,对于每次调用malloc
的OS,这取决于它的存储器管理算法,找到呼叫者最合适的/适当的/合适的/有效的自由空间。
例如:
void* p_1 = malloc(4);
void* p_2 = malloc(4);
[oooo][xxxx][oooo][oooo]
^ ^
p_1 p_2
什么关系呢?如果你需要连续的地址,你应该使用一个数组。 –
虽然这是错误的,但这是一个有趣的问题。除此之外,您可能预期内存位置是连续的 – Justin
您的地址相距32字节。如果它们是连续的,你会期望它们相距4个字节(假设'sizeof(int)== 4',它似乎通常是} – Justin