1.sizeof與strlen的區別。
#include <iostream>
using namespace std;
void main()
{cout << sizeof("hello") << endl;}
答案: 6
原因: “hello”={‘h’,'e','l','l','o','\0'};共六個字節。
那么sizeof與strlen有什么區別呢?
總結起來:
1).?sizeof 是運算符,在編譯時其值在編譯時即計算好了,參數可以是數組、指針、類型、對象、函數等。
? ? 而sgtrlen是函數,在運行時才知道大小?由于在編譯時計算,因此sizeof不能用來返回動態分配的內存空間的大小。實際上,用sizeof來返回類型以及靜態分配的對象、結構或數組所占的空間,返回值跟對象、結構、數組所存儲的內容沒有關系。
2).sizeof計算的是最大對象的字節大小,而strlen是計算實際存儲的字符個數。
3).sizeof的參數可以是數組、指針、類型、函數,而strlen只能是字符串指針或者數組。
2.內存空間分幾部分:BSS段、代碼段、數據段,棧,堆?
下面我們來簡單歸納一下進程對應的內存空間中所包含的5種不同的數據區都是干什么的。
BSS段:BSS段(bss segment)通常是指用來存放程序中未初始化的全局變量的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬于靜態內存分配。
數據段:數據段(data segment)通常是指用來存放程序中已初始化的全局變量的一塊內存區域。數據段屬于靜態內存分配。
代碼段:代碼段(code segment/text segment)通常是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經確定,并且內存區域通常屬于只讀, 某些架構也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數變量,例如字符串常量等。
堆(heap):堆是用于存放進程運行中被動態分配的內存段,它的大小并不固定,可動態擴張或縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)
棧(stack):棧又稱堆棧, 是用戶存放程序臨時創建的局部變量,也就是說我們函數括弧“{}”中定義的變量(但不包括static聲明的變量,static意味著在數據段中存放變量)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,并且待到調用結束后,函數的返回值也會被存放回棧中。由于棧的先進后出特點,所以棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的內存區。
它是由操作系統分配的,內存的申請與回收都由OS管理。
3.運算符和函數的區別
(1)語法形式上會有區別;
(2)運算符只能重載,不能自定義,函數的名字隨便你起,只要是個標志符就行;但運算符不行,比如,你無法仿照其它語言的符號,自己定義一個乘方運算符“**”。
(3)任何函數都可以重載或者覆蓋,但通常你不能改變運算符作用于內置類型的行為,比如你不能通過重載“operator+”,讓3?+?2產生出6來。
4.C++中malloc/free與new/delete的區別及內存分配失敗錯誤處理
首先談談C/C++內存分配失敗錯誤處理
一、C語言中的malloc/calloc/realloc/valloc/alloca/memalign函數:
這樣的內存分配函數在內存分配失敗時都返回空指針,因此,在調用返回時,檢查返回值的方法比較簡單,只需要與空指針比較即可;
如:
char* p = (char*)malloc(1204);
if(p == NULL)
{
//error handle;
};
char* pp = (char*)calloc(3,1024);
if(pp == NULL)
{
//error handle;
};
二、C++中的new操作符:
C++中的new操作符在分配內存失敗時默認的操作是拋出一個內置的異常,而并不是直接返回空指針;這樣的話,再把返回值與空指針比較,就沒有什么意義了;因為,C++拋出異常之后,就直接跳出new操作符所在的那一行代碼,而不再執行后續的代碼行了,所以,對new操作符返回值的判斷代碼就執行不到了;當然,標準C++也提供了抑制拋出異常的方法,使之不再排除內存分配失敗的異常,轉而直接返回空指針,這是因為比較古老的編譯器里面可能沒有異常處理機制,不能捕獲到異常;如:
int* p = new int[SIZE];
if(p == 0) //檢查p是否是空指針;這個判斷沒有意義;
{
return -1;
}
所以,在C++中有兩種方法來處理new操作符分配內存失敗的錯誤;
1、通過捕獲new操作符拋出的異常:
char* p = NULL;
try
{
p = new char[1024];
}
catch(const std::bad_alloc& ex)
{
//exception handle;
return -1;
}
2、抑制異常的拋出:
char* p = NULL;
p = new(std::nothrow)char[1024]; //這樣的話,如果new分配內存失敗,就不會再拋出異常,而是返回空指針了;
if(p == NULL) //這樣的判斷就有意義了;
{
//error handle;
return -1;
}
三、執行free或delete釋放內存之后,還需要做什么?
被free()掉的指針,我們通常叫野指針,野指針是非常危險的哦,可能導致多次釋放內存或者對野指針進行訪問,
這兩種情況都可能導致嚴重的安全風險。
最好的也是最簡單的解決辦法就是在釋放后,把指針設置為NULL或者指向另一個合法的對象。
就像這樣:
free(ptr);
ptr = NULL;
測試程序:
#include<iostream>
using namespace std; int main()
{ int *p = new int[5]; //_________使用new沒有必要檢查內存分配失敗 delete p; //此處為了驗證釋放p指針指向的內存之后,指針是否為NULL。答案是不會輸出Yes if (p == NULL) cout<<"Yes"<<endl; //為了避免“野指針”,必須給指針p重新賦值。此處置為NULL p = NULL; int *pp = (int *)malloc(sizeof(int)*5); //使用malloc有必要檢測 if (pp == NULL) { cout<<"error"<<endl; } free(pp); pp = NULL; return 0;
}
下面說說malloc/free與new/delete的區別及使用要點
相同點:都可用于申請動態內存和釋放內存
不同點:
(1)操作對象有所不同。
malloc與free是C++/C 語言的標準庫函數,new/delete 是C++的運算符。對于非內部數據類的對象而言,光用maloc/free 無法滿足動態對象的要求。對象在創建的同時要自動執行構造函數, 對象消亡之前要自動執行析構函數。由于malloc/free 是庫函數而不是運算符,不在編譯器控制權限之內,不能夠把執行構造函數和析構函數的任務強加malloc/free。
(2)用法上也有所不同。
函數malloc 的原型如下:
void * malloc(size_t size);
用malloc 申請一塊長度為length 的整數類型的內存,程序如下:
int *p = (int *) malloc(sizeof(int) * length);
我們應當把注意力集中在兩個要素上:“類型轉換”和“sizeof”。
1、malloc 返回值的類型是void *,所以在調用malloc 時要顯式地進行類型轉換,將void * 轉換成所需要的指針類型。
2、 malloc 函數本身并不識別要申請的內存是什么類型,它只關心內存的總字節數。
函數free 的原型如下:
void free( void * memblock );
為什么free 函數不象malloc 函數那樣復雜呢?這是因為指針p 的類型以及它所指的內存的容量事先都是知道的,語句free(p)能正確地釋放內存。如果p 是NULL 指針,那么free
對p 無論操作多少次都不會出問題。如果p 不是NULL 指針,那么free 對p連續操作兩次就會導致程序運行錯誤。
new/delete 的使用要點:
運算符new 使用起來要比函數malloc 簡單得多,例如:
int *p1 = (int *)malloc(sizeof(int) * length);
int *p2 = new int[length];
這是因為new 內置了sizeof、類型轉換和類型安全檢查功能。對于非內部數據類型的對象而言,new 在創建動態對象的同時完成了初始化工作。如果對象有多個構造函數,那么new 的語句也可以有多種形式。
如果用new 創建對象數組,那么只能使用對象的無參數構造函數。例如
Obj *objects = new Obj[100]; // 創建100 個動態對象
不能寫成
Obj *objects = new Obj[100](1); // 創建100 個動態對象的同時賦初值1
在用delete 釋放對象數組時,留意不要丟了符號‘[]’。例如
delete []objects; // 正確的用法
delete objects; // 錯誤的用法
后者相當于delete objects[0],漏掉了另外99 個對象。
/
1、new自動計算需要分配的空間,而malloc需要手工計算字節數
2、new是類型安全的,而malloc不是,比如:
int* p = new float[2]; // 編譯時指出錯誤
int* p = malloc(2*sizeof(float)); // 編譯時無法指出錯誤
new operator 由兩步構成,分別是 operator new 和 construct
3、operator new對應于malloc,但operator new可以重載,可以自定義內存分配策略,甚至不做內存分配,甚至分配到非內存設備上。而malloc無能為力
4、new將調用constructor,而malloc不能;delete將調用destructor,而free不能。
5、malloc/free要庫文件支持,new/delete則不要。
/
1、本質區別
malloc/free是C/C++語言的標準庫函數,new/delete是C++的運算符。
對于用戶自定義的對象而言,用maloc/free無法滿足動態管理對象的要求。對象在創建的同時要自動執行構造函數,對象在消亡之前要自動執行析構函數。由于malloc/free是庫函數而不是運算符,不在編譯器控制權限之內,不能夠把執行構造函數和析構函數的任務強加于malloc/free。因此C++需要一個能完成動態內存分配和初始化工作的運算符new,以及一個能完成清理與釋放內存工作的運算符delete。
class Obj
{
public: Obj( ) { cout << "Initialization" << endl; } ~ Obj( ) { cout << "Destroy" << endl; } void Initialize( ) { cout << "Initialization" << endl; } void Destroy( ) { cout << "Destroy" << endl; }
}obj; void UseMallocFree( )
{ Obj * a = (Obj *) malloc( sizeof ( obj ) ); // allocate memory a -> Initialize(); // initialization // … a -> Destroy(); // deconstruction free(a); // release memory
} void UseNewDelete( void )
{ Obj * a = new Obj; // … delete a;
}
類Obj的函數Initialize實現了構造函數的功能,函數Destroy實現了析構函數的功能。函數UseMallocFree中,由于malloc/free不能執行構造函數與析構函數,必須調用成員函數Initialize和Destroy來完成“構造”與“析構”。所以我們不要用malloc/free來完成動態對象的內存管理,應該用new/delete。由于內部數據類型的“對象”沒有構造與析構的過程,對它們而言malloc/free和new/delete是等價的。
2、聯系
既然new/delete的功能完全覆蓋了malloc/free,為什么C++還保留malloc/free呢?因為C++程序經常要調用C函數,而C程序只能用malloc/free管理動態內存。如果用free釋放“new創建的動態對象”,那么該對象因無法執行析構函數而可能導致程序出錯。如果用delete釋放“malloc申請的動態內存”,理論上講程序不會出錯,但是該程序的可讀性很差。所以new/delete、malloc/free必須配對使用。
這就是實例化的原因(空類同樣可以被實例化),每個實例在內存中都有一個獨一無二的地址,為了達到這個目的,編譯器往往會給一個空類隱含的加一個字節,這樣空類在實例化后在內存得到了獨一無二的地址,所以空類所占的內存大小是1個字節。
#include<iostream>
using namespace std
class a{};
int main()
{
cout<<"sizeof(a)="<<sizeof(a)<<endl;
return 0;
}
程序執行的輸出結果為:
sizeof(a)=1
以上程序驗證了空類所占內存為1個字節。
6.大小端
#include<iostream>
using namespace std;void main()
{
const char* p="\x12\x34\x56\x78";
printf("0x%x",*(int*)p);}
答案:0x78563412請按任意鍵繼續. . .
原因:
參考文獻:
1.《Sizeof與Strlen的區別與聯系》
2.《 sizeof和strlen之比較》
3.《C++中malloc/free與new/delete的區別及內存分配失敗錯誤處理》