內存分配問題

1.  內存基本構成
可編程內存基本上可以分爲3大部分:靜態存儲區、棧區和堆區。
靜態存儲區:內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。它主要存放靜態數據、全局數據和常量。

棧區:在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器的指令集中,效率很高,但是分配的內存容量有限。

堆區:亦稱動態分配區。程序在運行的時候用mallocC)或newC++)申請任意大小的內存,程序員自己負責在適當的時候用freeC)或deleteC++)釋放內存。mallocnew運算符返回的是一個指向所分配類型變量(對象)的指針。對所創建的變量或對象,都是通過該指針來間接操作的,而且動態創建的變量或對象本身沒有名字。動態內存的生存期可以由我們決定,如果我們不釋放內存,程序將在最後才釋放掉動態內存。良好的編程習慣是:如果某動態內存不再使用,需要將其釋放掉,否則,我們認爲發生了內存泄漏現象。另外,同一空間重複釋放也是危險的,因爲該空間可能已另分配。所以必須妥善保存mallocnew返回的指針,以保證不發生內存泄漏,也必須保證不會重複釋放堆內存空間。

2.  通過一些例子看一下數據在內存中是如何分配的
#include<iostream>
using namespace std;
void main()
{
  int a=5;
  int b=6;
  double f=3.141593;
  cout<<&a<<endl<<&b<<endl<<&f<<endl;
  cout<<a<<endl;
  cout<<*(&b+1)<<endl;
  cout<<*(&f+1)<<endl;
}
 
運行結果爲:
0012FF7C
0012FF78
0012FF70
5
5
1.061e-313
通過運行結果我們可以看出,內存分配是由高地址向低地址分配的。那爲什麼最後一句
的運行結果不是我們想要的b的值呢?這就涉及到了內存對齊問題,所以不要妄想着通過cout<<*(&f+1)<<endl;來得到b的值。
我們再看一個例子:
#include<iostream>
using namespace std;
void main()
{
  int a[5]={1,2,3,4,5};
  int b[5]={6,7,8,9,10};
  cout<<b[8]<<endl;
}
 
運行結果爲:4
爲什麼會出現這樣的結果呢?b[8]不是已經越界了嘛,爲什麼還會輸出結果呢。這是因
爲內存分配是從高地址向低地址分配的,且數組中的值在內存中是連續存放的。b[4]=10;已經到了數組的邊界了,但是因爲b數組下邊還存有a數組的元素,所以b[8]的值自然就是a[3]的值,也就是4啦。如果使用下邊的語句cout<<b[10]<<endl;系統不會報錯,但輸出的是一個隨機值。
我們可以通過下面的語句看一下b[8]a[3]的地址。
cout<<&b[8]<<endl;
          cout<<&a[3]<<endl;
運行結果爲:
0012FF78
0012FF78
這個結果就更證實了上邊的結果。
3.  看一些有關存儲區的例子
1
#include<iostream>
using namespace std;
void main()
{
  char *p="I Love China.";
  char str[]="I Love China";
  p[13]='!';
  str[13]='!';
  cout<<str[13]<<endl;
}
 
這個程序編譯時沒有出現異常,但是運行時卻出現了異常。通過加斷點跟蹤,發現是
p[13]=’!’;這條語句出錯了,爲什麼會出錯呢?難道通過指針不可以改變它所指向的內存單元中的內容嗎?這個要視情況而定,例如下面的程序就可以:
2
#include<iostream>
using namespace std;
void main()
{
  char ch='a';
  char *p=&ch;
  *p='b';
  cout<<ch<<endl;
}
運行結果:b
這是爲什麼呢?這是因爲例1p指向的是一個字符串常量的首地址,字符串常量是存放在靜態存儲區的,它的值是不能修改的。而數組時存放在棧區的,它的元素值是可以
修改的。例2中的ch是臨時變量,是存儲在棧區的,也是可以修改的。
棧區和堆區的區別有很多方面,大家可以上網搜一下,我就不在這裏贅述了。
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章