2017-07-28 45 views
6

我使用兩個變量,其中動態分配內存,並打印內存位置,但它們不是連續的。爲什麼?爲什麼動態分配的兩個變量的內存位置不連續?

#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 

爲什麼ab的存儲位置之間的確切區別是第一,第二和第三次變量的方式?

這與尋呼記憶有關嗎?

我的處理器是64位。

+2

什麼關係呢?如果你需要連續的地址,你應該使用一個數組。 –

+0

雖然這是錯誤的,但這是一個有趣的問題。除此之外,您可能預期內存位置是連續的 – Justin

+0

您的地址相距32字節。如果它們是連續的,你會期望它們相距4個字節(假設'sizeof(int)== 4',它似乎通常是} – Justin

回答

2

操作系統處理內存分配,並且不能保證在動態分配兩個連續變量時該內存是連續的。我還應該提到,這是一種稱爲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函數返回空指針或指向已分配空間的指針。

+0

謝謝@Miket –

+0

*「操作系統處理內存分配」* - 不一定是真的。一旦獲得內存,運行時可以提供分配,前提是內存以前是空閒的。另請參閱[請問malloc實現是否將釋放內存返回給系統?](https://stackoverflow.com/q/2215259/608639) – jww

-2

如果你想連續的內存分配內存和unique_ptr與兩個數組的大小,並指向你的指針的末尾和指針的中心,你從獨特的指針得到。只記得不要刪除你的a和b指針。

std::unique_ptr<int> a(new int[na+nb]) 
int * aptr = a.get(); 
Int * bptr = a.get() + na; 
8

兩個連續分配之間的差距與尋呼無關。您的分配太小以至於它們駐留在數據段中。 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.如果您確實需要爲連續地址動態分配空間,請分配一個數組。

+0

那麼爲什麼指針值每次都不相同? – EJP

+0

@EJP補充說也是 –

+0

謝謝@ antti haapala ..但是我不希望那個記憶是連續的..爲什麼它不是連續的是我的問題..以及我第一次提到我的記憶位置,第二次和第三次我的程序執行..如果你觀察到的位置和差異b/w的內存位置alloctaed ..如果發現有些模棱兩可... –

0

隨着音符在GNU Examples of malloc

需要注意的是位於該塊結束後的內存可能 在使用別的東西;也許一個塊已經被 分配給malloc的另一個調用。

這實際上意味着,對於每次調用malloc的OS,這取決於它的存儲器管理算法,找到呼叫者最合適的/適當的/合適的/有效的自由空間。

例如:

void* p_1 = malloc(4); 
void* p_2 = malloc(4); 

[oooo][xxxx][oooo][oooo] 
^   ^
p_1   p_2 
相關問題