C++內存布局(1)-讓new出的兩個變量在堆上的地址連續


大家都知道棧的地址按照從高到低的順序增長的,

而堆的地址是按照從底到高的順序增長的。

int *n1 = new int(1);
int *n2 = new int(2);
cout<<"n1,n2所指的地址:" << n1 << "  " << n2<<" " <<"相差:"<<(int)n1-(int)n2<<endl;
cout << "n1,n2的地址    :" << &n1 << "  " << &n2 <<" "<<"相差:"<< (int)&n1 - (int)&n2 << endl;
cout << sizeof(int*) << endl;

n1和n2是儲存在棧上的

而它們所指的空間是位於堆上的

這里我發現在VS2013 debug模式下的結果是,n2和n1相差了12而不是8

image_thumb[2]

觀察內存布局我發現

image_thumb[4]

n1和n2之間隔了很多cc,查閱后發現是為了越界之后,造成軟中斷方便調試之用的。運行下面的程序可以發現產生了一個中斷(觸發斷點)

int main()
{
    //嵌入匯編
    //int表示觸發軟中斷,3是中斷號,
    //代碼int 3在內存中剛好是一個字節CC
    __asm int 3;
    return 0;
}

切換到release下發現

image_thumb[5]

n1和n2之間差的值變成了8

 

*這里n1比n2地址小的原因是

多核CPU經常會並行同時運行一些沒有因果關系的語句,n2申請空間時沒有使用n1的數據,編譯器就可以優化成先申請n2,再申請n1,或先申請n1,再申請n2,或者兩個並行同時申請(感謝群里的C++大神指點)。

 

可以看到棧的增長是按照從高到的低的順序

而堆的增長是按照從低到高的順序

 

同時我們也可以看成棧分配的內存是連續的

而堆的分配的內存是不連續的

 

哪我們有沒有辦法使堆的分配在兩個連續的內存上呢?

方法是我們可以先分配一個大的內存

然后再這塊內存上進行我們的操作

 

void *p1 = malloc(2 * sizeof(int));
void *p2=(int*)p1 + 1;
int *t1 = new (p1)int(1);
int *t2 = new (p2)int(2);
cout << "t1,t2所指的地址:" << t1 << "  " << t2 << endl;
cout << "t1,t2的地址    :" << &t1 << "  " << &t2 << endl;

我們先用malloc分配出一塊大小為兩個int的內存

這時p1指向這塊內存的起點

我們再將p1移動int個大小的內存得到了p2

然后分別在p1和p2所指的地址上構建變量

這樣就使的new出的兩個變量在堆上的地址連續了

 

debug下

image_thumb[7]

release下

image_thumb[6]

 

棧(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。分配方式類似於數據結構中的棧。

堆(heap) — 由程序員分配釋放, 若程序員不釋放,程序結束時由OS回收 。分配方式倒是類似於鏈表。

int *t1 = new (p1)int(1) — 重載operator new 的一個標准、全局的版本,原型是void *operator new( size_t, void *p ) throw() { return p; }在p所指的地方分配內存


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM