基本類型和變量.
像其他高級(jí)語(yǔ)言一樣,ISO C++除了像C一樣,有自己的基本類型:字符型,整形,浮點(diǎn)型等,還提供了可用于自定義類型機(jī)制.所謂的C++ STL,正是這個(gè)機(jī)制定義了大量的類型和操作.
比如可變長(zhǎng)的string,vector等.一般和C一樣,也是為了兼容C,內(nèi)置類型一般小寫.
對(duì)于所謂內(nèi)置類型不同,一般指位數(shù)不同而已,比如int 16(當(dāng)然這個(gè)有爭(zhēng)議,很多語(yǔ)言都是32位,所以C++又定義了一個(gè)long 32)和float(32位),當(dāng)然也有不同的類型位數(shù)一樣,比如剛才int 和 short都是16.
其實(shí)所有的這一切都是編譯器想怎么解釋就怎么解釋(也有標(biāo)準(zhǔn)的約束).
像C語(yǔ)言一樣,C++的字符用單引號(hào),字符串用雙引號(hào),這點(diǎn)和pascal不同,pascal都用單引號(hào),編譯器自行解釋.另外,和pascal不同的是,C++/C定義常量,也用特殊標(biāo)識(shí),比如字符串前加"L"代表unicode串,整形后加L表示long型,也就是32位的.
與C一樣,都用""作轉(zhuǎn)義字符.整形和字符型在一定范圍兼容.
作用域:C++比C多了名字空間作用域,類作用域(其實(shí)C也有struct作用域).
頭文件,C直接用.h結(jié)尾的文件,而現(xiàn)在的C++頭文件一般都不帶.h,比如 #include <string> #include <string.h>,前者定義有string類型,而后者則是一些char *處理函數(shù).
C/C++都有特殊類型,引用(符號(hào)&), 引用其實(shí)就是一個(gè)變量的別名,僅此而已.像const變量一樣,引用必須初始化. 如:int i; int &reint = i;正因?yàn)橐檬莿e名,所以不能直接對(duì)其賦值,&reint = i;(error).
枚舉類型:其實(shí)就是定義一些常量的集合.關(guān)鍵字enum mode {input,output,append};枚舉類型都有默認(rèn)的值,從第一個(gè)為0開始,后面依次加1,input = 0,output = 1,append =2.當(dāng)然也可以給定其初始化值.enum mode {input = 1,output,append};
像C一樣,關(guān)鍵字typedef可以定義復(fù)雜的類型.比如typedef void (Message_Process::*FN_Msg)(Message*); FN_Msg為函數(shù)指針類型,可以用其定義其他的變量,比如FN_Msg p = NULL;
與C不同的是,C++有class關(guān)鍵字.標(biāo)準(zhǔn)庫(kù)通過(guò)他,定義大量的數(shù)據(jù)類型,比如string,istream,ostream等等.雖然class和 struct差不多,但class機(jī)制更復(fù)雜,主要就是他定義了一組權(quán)限規(guī)則,private,protected,public.(記得類后面有;號(hào)啊)struct內(nèi)部的成員都是public屬性.
C++標(biāo)準(zhǔn)庫(kù)(STL)
首先名字空間using namespace std; 當(dāng)然也可以直接using std::cin;
現(xiàn)在我們來(lái)玩玩string這個(gè)東東.這個(gè)東東在pascal里也有,內(nèi)存分配是 引用計(jì)數(shù) +Length + ansichar*,在string里,在C++里只知道是一個(gè)常用對(duì)象,具體怎么分配的,網(wǎng)上好多垃圾也沒(méi)有說(shuō)清楚.只說(shuō)什么copyonwrite亂七八糟之云乎.既然是類,那么就要遵循C++實(shí)例規(guī)則.C++沒(méi)有pascal那么嚴(yán)格,pascal里只有明確的create才能創(chuàng)造對(duì)象,C++到處都暗藏殺機(jī).很多隱式定義.
string定義(四種):
string s1;
string s2(s1);//定義并初始化
string s3("value");//常量初始化
string s4(n,'c');//相同字符常量初始化
運(yùn)算符重載(+,=(賦值),==,!=,>,<等等)
成員函數(shù)size和empty判斷長(zhǎng)度.
string::size_type類型
template<class E, //定義模板類,泛型化
class T = char_traits<E>, //T,A也一個(gè)泛型實(shí)例的類
class A = allocator<T> > //泛型類
class basic_string {
public:
typedef T traits_type; //定義泛型類型
typedef A allocator_type;
typedef T::char_type char_type; //這里A和T只是一個(gè)類域而已
typedef A::size_type size_type;
typedef A::difference_type difference_type;
typedef A::pointer pointer;
typedef A::const_pointer const_pointer;
typedef A::reference reference;
typedef A::const_reference const_reference;
typedef A::value_type value_type;
typedef T0 iterator;
typedef T1 const_iterator;
typedef reverse_iterator<iterator, value_type,
reference, pointer, difference_type>
reverse_iterator;
typedef reverse_iterator<const_iterator, value_type,
const_reference, const_pointer, difference_type>
const_reverse_iterator;
static const size_type npos = -1;
//隱式構(gòu)造函數(shù) ,以下都是其構(gòu)造函數(shù)
explicit basic_string(const A& al = A()); //string str;分配一空字符串
basic_string(const basic_string& rhs); //string str(s1);
basic_string(const basic_string& rhs, size_type pos, size_type n, //string s4(str,1,5);用另一個(gè)字符串的一節(jié)去構(gòu)造
const A& al = A());
basic_string(const E *s, size_type n, const A& al = A()); //
basic_string(const E *s, const A& al = A());
basic_string(size_type n, E c, const A& al = A());
basic_string(const_iterator first, const_iterator last, //可以看出,共有7種構(gòu)造函數(shù)
const A& al = A());
basic_string& operator=(const basic_string& rhs); //賦值運(yùn)算符重載
basic_string& operator=(const E *s);
basic_string& operator=(E c); //三種賦值運(yùn)算
iterator begin(); //實(shí)現(xiàn)了迭代器算法
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
const_reference at(size_type pos) const;
reference at(size_type pos);
const_reference operator[](size_type pos) const; //下標(biāo)重載
reference operator[](size_type pos);
const E *c_str() const; //返回c格式的字符串函數(shù)
const E *data() const; //.
size_type length() const; //長(zhǎng)度大小操作
size_type size() const;
size_type max_size() const;
void resize(size_type n, E c = E());
size_type capacity() const;
void reserve(size_type n = 0);
bool empty() const;
basic_string& operator+=(const basic_string& rhs); //+=重載
basic_string& operator+=(const E *s);
basic_string& operator+=(E c);
軟件開發(fā)網(wǎng)
basic_string& append(const basic_string& str); //添加
basic_string& append(const basic_string& str,
size_type pos, size_type n);
basic_string& append(const E *s, size_type n);
basic_string& append(const E *s);
basic_string& append(size_type n, E c);
basic_string& append(const_iterator first, const_iterator last);
basic_string& assign(const basic_string& str); //賦值
basic_string& assign(const basic_string& str,
size_type pos, size_type n);
basic_string& assign(const E *s, size_type n);
basic_string& assign(const E *s);
basic_string& assign(size_type n, E c);
basic_string& assign(const_iterator first, const_iterator last);
basic_string& insert(size_type p0,
const basic_string& str);
basic_string& insert(size_type p0,
const basic_string& str, size_type pos, size_type n);
basic_string& insert(size_type p0,
const E *s, size_type n);
basic_string& insert(size_type p0, const E *s);
basic_string& insert(size_type p0, size_type n, E c);
iterator insert(iterator it, E c);
void insert(iterator it, size_type n, E c);
void insert(iterator it,
const_iterator first, const_iterator last);
basic_string& erase(size_type p0 = 0, size_type n = npos);
iterator erase(iterator it);
iterator erase(iterator first, iterator last);
basic_string& replace(size_type p0, size_type n0,
const basic_string& str);
basic_string& replace(size_type p0, size_type n0,
const basic_string& str, size_type pos, size_type n);
basic_string& replace(size_type p0, size_type n0,
const E *s, size_type n);
basic_string& replace(size_type p0, size_type n0,
const E *s);
basic_string& replace(size_type p0, size_type n0,
size_type n, E c);
basic_string& replace(iterator first0, iterator last0,
const basic_string& str);
basic_string& replace(iterator first0, iterator last0,
const E *s, size_type n);
basic_string& replace(iterator first0, iterator last0,
const E *s);
basic_string& replace(iterator first0, iterator last0,
size_type n, E c);
basic_string& replace(iterator first0, iterator last0,
const_iterator first, const_iterator last);
size_type copy(E *s, size_type n, size_type pos = 0) const;
void swap(basic_string& str);
size_type find(const basic_string& str,
size_type pos = 0) const;
size_type find(const E *s, size_type pos, size_type n) const;
size_type find(const E *s, size_type pos = 0) const;
size_type find(E c, size_type pos = 0) const;
size_type rfind(const basic_string& str,
size_type pos = npos) const;
size_type rfind(const E *s, size_type pos,
size_type n = npos) const;
size_type rfind(const E *s, size_type pos = npos) const;
size_type rfind(E c, size_type pos = npos) const;
size_type find_first_of(const basic_string& str,
size_type pos = 0) const;
size_type find_first_of(const E *s, size_type pos,
size_type n) const;
size_type find_first_of(const E *s, size_type pos = 0) const;
size_type find_first_of(E c, size_type pos = 0) const;
size_type find_last_of(const basic_string& str,
size_type pos = npos) const;
size_type find_last_of(const E *s, size_type pos,
size_type n = npos) con/t;
size_type find_last_of(const E *s, size_type pos = npos) const;
size_type find_last_of(E c, size_type pos = npos) const;
size_type find_first_not_of(const basic_string& str,
size_type pos = 0) const;
size_type find_first_not_of(const E *s, size_type pos,
size_type n) const;
size_type find_first_not_of(const E *s, size_type pos = 0) const;
size_type find_first_not_of(E c, size_type pos = 0) const;
size_type find_last_not_of(const basic_string& str,
size_type pos = npos) const;
size_type find_last_not_of(const E *s, size_type pos,
size_type n) const;
size_type find_last_not_of(const E *s,
size_type pos = npos) const;
size_type find_last_not_of(E c, size_type pos = npos) const;
basic_string substr(size_type pos = 0, size_type n = npos) const;
int compare(const basic_string& str) const;
int compare(size_type p0, size_type n0,
const basic_string& str);
int compare(size_type p0, size_type n0,
const basic_string& str, size_type pos, size_type n);
int compare(const E *s) const;
int compare(size_type p0, size_type n0,
const E *s) const;
int compare(size_type p0, size_type n0,
const E *s, size_type pos) const;
A get_allocator() const;
protected:
A allocator;
};
iterator(迭代器)
他的存在主要是為了集合數(shù)據(jù)的安全訪問(wèn).也是提供一些遍歷的方法.
begin和end操作.返回一個(gè)iterator.
vector<int>::iterator iter = ivec.begin();//返回容器的第一個(gè)元素iterator.
iterator還重載了許多符號(hào),比如*,-,+等,以實(shí)現(xiàn)簡(jiǎn)單快捷安全的訪問(wèn)元素.
*iter = 0;//對(duì)當(dāng)前元素賦值.
這里值得一提的是,當(dāng)容器的元素增加,刪除,或交換,該容器的iterator將失效,得重新檢索得到iterator.
template<class C, class T, class Dist = ptrdiff_t> //ptrdiff_t是一個(gè)run-time library定義的類型
struct iterator { //可以看iterator是一個(gè)沒(méi)有任何操作的模板結(jié)構(gòu).
typedef C iterator_category;
typedef T value_type;
typedef Dist distance_type;
};
而真正的具體定義卻也只是像下面這樣一句話而已.
typedef _A::pointer iterator;
typedef _A::const_pointer const_iterator;
//下面是他的具體實(shí)現(xiàn)
iterator begin()
{_Freeze();
return (_Ptr); }
const_iterator begin() const
{return (_Ptr); }
iterator end()
{_Freeze();
return ((iterator)_Psum(_Ptr, _Len)); }
const_iterator end() const
{return ((const_iterator)_Psum(_Ptr, _Len)); }
unsigned char& _Refcnt(const _E *_U) //字符串的引用,最大引用255次
{return (((unsigned char *)_U)[-1]); } //返回字符串內(nèi)存中的前面一個(gè)字符
void _Freeze()
{if (_Ptr != 0
&& _Refcnt(_Ptr) != 0 && _Refcnt(_Ptr) != _FROZEN)
_Grow(_Len);
if (_Ptr != 0)
_Refcnt(_Ptr) = _FROZEN; }
_E *_Ptr;//而_E此時(shí)是char,即指向string的首個(gè)字符
_E *_Ptr;
size_type _Len, _Res;
//真正的字符串只存儲(chǔ)_Refcnt和char array[_Len]數(shù)組.
//從這上面可以看出,string對(duì)象內(nèi)存只存儲(chǔ)三個(gè)變量,第一個(gè)首字母指針,
//第二個(gè)是長(zhǎng)度,第三個(gè)應(yīng)該最大長(zhǎng)度.因?yàn)閟tring是一個(gè)可自動(dòng)加長(zhǎng)的類型.
可以看出,string的內(nèi)存實(shí)現(xiàn),很簡(jiǎn)單并且引用了_Refcnt機(jī)制,這個(gè)機(jī)制可以幫助我們實(shí)現(xiàn)copy_on_write.
但是可以明顯看到,這點(diǎn)也給我們帶來(lái)了麻煩.在多線程編程中,_Refcnt很容易被破壞,造成內(nèi)存錯(cuò)誤或者內(nèi)存泄漏.
這點(diǎn)應(yīng)該向pascal學(xué)習(xí)了,delphi的string增加了鎖機(jī)制,所以可以很好在多線程使用.
struct char_traits<E> { //一個(gè)基本操作類模板,可以看出里面全部都是靜態(tài)成員函數(shù),
typedef E char_type; //所以只給其他類用,不實(shí)例對(duì)象
typedef T1 int_type;
typedef T2 pos_type;
typedef T3 off_type;
typedef T4 state_type;
static void assign(E& x, const E& y);
static E *assign(E *x, size_t n, const E& y);
static bool eq(const E& x, const E& y);
static bool lt(const E& x, const E& y);
static int compare(const E *x, const E *y, size_t n);
static size_t length(const E *x);
static E *copy(E *x, const E *y, size_t n);
static E *move(E *x, const E *y, size_t n);
static const E *find(const E *x, size_t n, const E& y);
static E to_char_type(const int_type& ch);
static int_type to_int_type(const E& c);
static bool eq_int_type(const int_type& ch1, const int_type& ch2);
static int_type eof();
static int_type not_eof(const int_type& ch);
};
軟件開發(fā)網(wǎng)
以上可以看了,basic_string并沒(méi)有重載一些常用的運(yùn)算符,但實(shí)際我們又經(jīng)??梢杂玫?比如 +,>,<,==等等
即沒(méi)有像下面的
bool basic_string::operator<(const basic_string &rhs);
basic_string& basic_string::operator+(const basic_string &rhs);
等等,其實(shí)我猜測(cè)應(yīng)該是編譯器,把這些自行的解釋了,比如<就用compare操作代替.當(dāng)然我對(duì)C++沒(méi)有什么深入研究的,只是猜測(cè).
typedef basic_string<char> string;//這就是真正的string的全部,就一句話.表明它是操作char 的東東.
vector類型(不像string,而是一個(gè)類模板.)
同一類型對(duì)象的組合,像基本類型數(shù)組,我們稱之為"容器".vector本身并不是直接類,也就是不能直接使用,在經(jīng)過(guò)模板實(shí)例化.
vector也有好幾種構(gòu)造函數(shù).
vector<T> v1; //構(gòu)造空的vector對(duì)象.
vector<T> v2(v1); //將v1作副本構(gòu)造一個(gè)vector對(duì)象.
vector<T> v3(n,i); //包含n個(gè)值為i的元素vector對(duì)象.
vector<T> v4(n); //包含n個(gè)值為初始化的元素的vector對(duì)象.
vector用引用對(duì)象初始化的時(shí)候,要保持兼容性.
template<class T, class A = allocator<T> >
class vector {
public:
typedef A allocator_type;
typedef A::size_type size_type;
typedef A::difference_type difference_type;
typedef A::reference reference;
typedef A::const_reference const_reference;
typedef A::value_type value_type;
typedef T0 iterator; //這里定義一個(gè)迭代器.
typedef T1 const_iterator;
typedef reverse_iterator<iterator, value_type,
reference, A::pointer, difference_type>
reverse_iterator;
typedef reverse_iterator<const_iterator, value_type,
const_reference, A::const_pointer, difference_type>
const_reverse_iterator;
//以下是vector的四個(gè)構(gòu)造函數(shù)
explicit vector(const A& al = A());
explicit vector(size_type n, const T& v = T(), const A& al = A());
vector(const vector& x);
vector(const_iterator first, const_iterator last,
const A& al = A());
void reserve(size_type n);
size_type capacity() const; 軟件開發(fā)網(wǎng)
iterator begin(); //實(shí)現(xiàn)了迭代器
const_iterator begin() const;
iterator end();
iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
void resize(size_type n, T x = T()); //一些基本操作
size_type size() const;
size_type max_size() const;
bool empty() const;
A get_allocator() const;
reference at(size_type pos);
const_reference at(size_type pos) const;
reference operator[](size_type pos); //下標(biāo)操作
const_reference operator[](size_type pos);
reference front();
const_reference front() const;
reference back();
const_reference back() const;
void push_back(const T& x);
void pop_back();
void assign(const_iterator first, const_iterator last);
void assign(size_type n, const T& x = T());
iterator insert(iterator it, const T& x = T());
void insert(iterator it, size_type n, const T& x);
void insert(iterator it,
const_iterator first, const_iterator last);
iterator erase(iterator it);
iterator erase(iterator first, iterator last);
void clear();
void swap(vector x);
protected:
A allocator; //包含一個(gè)對(duì)象分配器
};
template<class T>
class allocator { //對(duì)象分配器
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T *pointer;
typedef const T *const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
pointer address(reference x) const; //地址及地址指針
const_pointer address(const_reference x) const;
allocator(); //構(gòu)造函數(shù) 軟件開發(fā)網(wǎng)
allocator<T>& operator=(const allocator<T>); //基本的賦值運(yùn)算
pointer allocate(size_type n, const void *hint);
void deallocate(pointer p, size_type n); //釋放對(duì)象
void construct(pointer p, const T& val); //構(gòu)造內(nèi)存對(duì)象
void destroy(pointer p); //釋放指針
size_type max_size() const;
}; 軟件開發(fā)網(wǎng)
具體iterator實(shí)現(xiàn)
typedef _A::pointer _Tptr; //普通指針
typedef _A::const_pointer _Ctptr; //這時(shí)僅僅是一個(gè)常指針類型
typedef _A::reference reference;
typedef _A::const_reference const_reference;
typedef _A::value_type value_type;
typedef _Tptr iterator; //這就是vector的iterator的全部
typedef _Ctptr const_iterator; //vertor的const_iterator
iterator begin()
{return (_First); }
const_iterator begin() const
{return ((const_iterator)_First); }
iterator end()
{return (_Last); }
const_iterator end() const
{return ((const_iterator)_Last); }
_A allocator;
iterator _First, _Last, _End;
//從上面可以看vector只有四個(gè)成員元素,第一個(gè)對(duì)象分配器,接下來(lái)的三個(gè),其實(shí)都是一個(gè)普通指針而已. 軟件開發(fā)網(wǎng)
依次分析,其實(shí)所謂的iterator的*,+,-操作都是C++編譯器的內(nèi)置的指針操作而已.
另外上面的可以看出,上面的每個(gè)類都定義了好多const操作.其實(shí)const既可以定義變量,也可以定義類成員函數(shù)(此時(shí)放在類的成員函數(shù)后面).
當(dāng)const修飾變量的時(shí)候,表明此變量不能修改.當(dāng)const修改類成員函數(shù),表明此函數(shù)不能修改類的成員元素.
上面只了解了幾個(gè)常用的標(biāo)準(zhǔn)庫(kù),還有很多類似的庫(kù).
軟件開發(fā)網(wǎng)
下面介紹下new和delete關(guān)鍵字.
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
int i;
string *psa = new string[3]; //這里下斷點(diǎn)以跟蹤
for (i=0;i<3;i++) {
psa[i] = "huzg";
}
for (i=0;i<3;i++) {
cout << psa[i] <<endl;
}
delete [] (psa); //這里調(diào)用了vector deleting destructor.
return 0;
}
9: string *psa = new string[3];
0040126D push 34h //這里其實(shí)是實(shí)際大小,34h=52
0040126F call operator new (00409840) //這里調(diào)用C++編譯器內(nèi)置函數(shù)operator new
00401274 add esp,4
operator new:
00409840 push ebp
00409841 mov ebp,esp
00409843 push ecx
00409844 push 1
00409846 mov eax,dword ptr [cb]
00409849 push eax
0040984A call _nh_malloc (0040a5a0)
0040984F add esp,8
00409852 mov dword ptr [res],eax
00409855 mov eax,dword ptr [res]
00409858 mov esp,ebp
0040985A pop ebp 軟件開發(fā)網(wǎng)
0040985B ret
--- No source file -----------------------
0040985C int 3
0040985D int 3
0040985E int 3
0040985F int 3
//CRT內(nèi)new的源碼new.cpp
void * operator new( unsigned int cb )
{
void *res = _nh_malloc( cb, 1 );
return res;
}
//_nh_malloc又進(jìn)入了DbgHeap.c文件里
void * __cdecl _nh_malloc (
size_t nSize,
int nhFlag
)
{
return _nh_malloc_dbg(nSize, nhFlag, _NORMAL_BLOCK, NULL, 0);
}
//此函數(shù)是__cdecl,和__stdcall一樣都是從右到左壓棧,但__cdecl棧是調(diào)用者來(lái)維護(hù),也就是調(diào)用它函數(shù)清棧,__stdcall則是函數(shù)自己來(lái)維護(hù).
void * __cdecl _nh_malloc_dbg (
size_t nSize, //34h
int nhFlag, //1
int nBlockUse, //1
const char * szFileName, //0
int nLine //0
)
{
void * pvBlk;
for (;;)
{
#ifdef _MT
/* lock the heap
*/
_mlock(_HEAP_LOCK);
__try {
#endif /* _MT */
軟件開發(fā)網(wǎng)
/* do the allocation
*/
pvBlk = _heap_alloc_dbg(nSize, nBlockUse, szFileName, nLine);
#ifdef _MT
}
__finally {
/* unlock the heap
*/
_munlock(_HEAP_LOCK);
}
#endif /* _MT */
if (pvBlk || nhFlag == 0)
return pvBlk;
/* call installed new handler */
if (!_callnewh(nSize))
return NULL;
/* new handler was successful -- try to allocate again */
}
}
void * __cdecl _heap_alloc_dbg(
size_t nSize,
int nBlockUse,
const char * szFileName,
int nLine
)
{
long lRequest;
size_t blockSize;
int fIgnore = FALSE;
_CrtMemBlockHeader * pHead;
/* verify heap before allocation */
if (_crtDbgFlag & _CRTDBG_CHECK_ALWAYS_DF)
_ASSERTE(_CrtCheckMemory());
lRequest = _lRequestCurr; 軟件開發(fā)網(wǎng)
/* break into debugger at specific memory allocation */
if (lRequest == _crtBreakAlloc)
_CrtDbgBreak();
_CrtDefaultAllocHook:
00410E30 push ebp
00410E31 mov ebp,esp
00410E33 mov eax,1
00410E38 pop ebp
00410E39 ret
/* forced failure */
if (!(*_pfnAllocHook)(_HOOK_ALLOC, NULL, nSize, nBlockUse, lRequest, szFileName, nLine)) //這里進(jìn)入系統(tǒng)給出的函數(shù)_CrtDefaultAllocHook:
{
if (szFileName)
_RPT2(_CRT_WARN, "Client hook allocation failure at file %hs line %d.n",
szFileName, nLine);
else
_RPT0(_CRT_WARN, "Client hook allocation failure.n");
return NULL;
}
/* cannot ignore CRT allocations */
if (_BLOCK_TYPE(nBlockUse) != _CRT_BLOCK &&
!(_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF))
fIgnore = TRUE;
/* Diagnostic memory allocation from this point on */
if (nSize > (size_t)_HEAP_MAXREQ ||
nSize + nNoMansLandSize + sizeof(_CrtMemBlockHeader) > (size_t)_HEAP_MAXREQ)
{
_RPT1(_CRT_ERROR, "Invalid allocation size: %u bytes.n", nSize);
return NULL;
}
if (!_BLOCK_TYPE_IS_VALID(nBlockUse))
{
_RPT0(_CRT_ERROR, "Error: memory allocation: bad memory block type.n");
}
blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize;
#ifndef WINHEAP
/* round requested size */
blockSize = _ROUND2(blockSize, _GRANULARITY);
#endif /* WINHEAP */
pHead = (_CrtMemBlockHeader *)_heap_alloc_base(blockSize); //進(jìn)入_heap_alloc_base
if (pHead == NULL)
return NULL;
軟件開發(fā)網(wǎng)
/* commit allocation */
++_lRequestCurr;
if (fIgnore)
{
pHead->pBlockHeaderNext = NULL;
pHead->pBlockHeaderPrev = NULL;
pHead->szFileName = NULL;
pHead->nLine = IGNORE_LINE;
pHead->nDataSize = nSize;
pHead->nBlockUse = _IGNORE_BLOCK;
pHead->lRequest = IGNORE_REQ;
}
else {
/* keep track of total amount of memory allocated */
_lTotalAlloc += nSize;
_lCurAlloc += nSize;
if (_lCurAlloc > _lMaxAlloc)
_lMaxAlloc = _lCurAlloc;
if (_pFirstBlock)
_pFirstBlock->pBlockHeaderPrev = pHead;
else
_pLastBlock = pHead;
pHead->pBlockHeaderNext = _pFirstBlock;
pHead->pBlockHeaderPrev = NULL;
pHead->szFileName = (char *)szFileName;
pHead->nLine = nLine;
pHead->nDataSize = nSize;
pHead->nBlockUse = nBlockUse;
pHead->lRequest = lRequest;
軟件開發(fā)網(wǎng)
/* link blocks together */
_pFirstBlock = pHead;
}
/* fill in gap before and after real block */
memset((void *)pHead->gap, _bNoMansLandFill, nNoMansLandSize);
memset((void *)(pbData(pHead) + nSize), _bNoMansLandFill, nNoMansLandSize);
/* fill data with silly value (but non-zero) */
memset((void *)pbData(pHead), _bCleanLandFill, nSize);
return (void *)pbData(pHead);
}
//進(jìn)入malloc.c的_heap_alloc_base
void * __cdecl _heap_alloc_base (size_t size)
{
#ifdef WINHEAP
void * pvReturn;
#else /* WINHEAP */
_PBLKDESC pdesc;
_PBLKDESC pdesc2;
#endif /* WINHEAP */
#ifdef WINHEAP
if ( __active_heap == __V6_HEAP )
{
if ( size <= __sbh_threshold )
{
#ifdef _MT
_mlock( _HEAP_LOCK );
__try {
#endif /* _MT */
pvReturn = __sbh_alloc_block(size);
#ifdef _MT
}
__finally {
_munlock( _HEAP_LOCK );
}
#endif /* _MT */
if (pvReturn)
return pvReturn;
}
}
else if ( __active_heap == __V5_HEAP )
{
/* round up to the nearest paragraph */
if ( size )
size = (size + _OLD_PARASIZE - 1) & ~(_OLD_PARASIZE - 1);
else 軟件開發(fā)網(wǎng)
size = _OLD_PARASIZE;
if ( size <= __old_sbh_threshold ) {
#ifdef _MT
_mlock(_HEAP_LOCK);
__try {
#endif /* _MT */
pvReturn = __old_sbh_alloc_block(size >> _OLD_PARASHIFT);
#ifdef _MT
}
__finally {
_munlock(_HEAP_LOCK);
}
#endif /* _MT */
if ( pvReturn != NULL )
return pvReturn;
}
return HeapAlloc( _crtheap, 0, size );//最終走到這里,直接調(diào)用ntdll里的HeapAlloc函數(shù),沒(méi)有內(nèi)核符號(hào),不能再跟蹤了.
}
軟件開發(fā)網(wǎng)
if (size == 0)
size = 1;
size = (size + BYTES_PER_PARA - 1) & ~(BYTES_PER_PARA - 1);
return HeapAlloc(_crtheap, 0, size);
}
#else /* WINHEAP */
/* try to find a big enough free block
*/
if ( (pdesc = _heap_search(size)) == NULL )
{
if ( _heap_grow(size) != -1 )
{
/* try finding a big enough free block again. the
* success of the call to _heap_grow should guarantee
* it, but...
*/
if ( (pdesc = _heap_search(size)) == NULL )
{
/* something unexpected, and very bad, has
* happened. abort!
*/
_heap_abort();
}
}
else
return NULL;
}
軟件開發(fā)網(wǎng)
/* carve the block into two pieces (if necessary). the first piece
* shall be of the exact requested size, marked inuse and returned to
* the caller. the leftover piece is to be marked free.
*/
if ( _BLKSIZE(pdesc) != size ) {
/* split up the block and free the leftover piece back to
* the heap
*/
if ( (pdesc2 = _heap_split_block(pdesc, size)) != NULL )
_SET_FREE(pdesc2);
}
/* mark pdesc inuse
*/
_SET_INUSE(pdesc);
/* check proverdesc and reset, if necessary
*/
_heap_desc.proverdesc = pdesc->pnextdesc;
return( (void *)((char *)_ADDRESS(pdesc) + _HDRSIZE) );
}
delete[] psa;
//這里應(yīng)該調(diào)用了basic_string析構(gòu)函數(shù),而basic_string析構(gòu)函數(shù)只有一個(gè):~basic_string(){_Tidy(true); }
具體調(diào)用如下:
std::basic_string<char,std::char_traits<char>,std::allocator<char> >::`vector deleting destructor':
00401419 call `eh vector destructor iterator' (00409db0)
//最后再調(diào)用basic_string析構(gòu)函數(shù)
58: ~basic_string()
59: {_Tidy(true); }
00401550 push ebp
00401551 mov ebp,esp
00401553 sub esp,44h
00401556 push ebx
00401557 push esi
00401558 push edi
00401559 push ecx
0040155A lea edi,[ebp-44h]
0040155D mov ecx,11h
00401562 mov eax,0CCCCCCCCh
00401567 rep stos dword ptr [edi]
00401569 pop ecx
0040156A mov dword ptr [ebp-4],ecx
0040156D push 1
0040156F mov ecx,dword ptr [ebp-4]
00401572 call @ILT+25(std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy) (00
00401577 pop edi
00401578 pop esi
00401579 pop ebx
0040157A add esp,44h
0040157D cmp ebp,esp
0040157F call __chkesp (00409c80)
00401584 mov esp,ebp
00401586 pop ebp
00401587 ret
--- No source file ---------------------------------------------------------------------------------------------------------------------------------------
00401588 int 3
00401589 int 3
0040158A int 3
void _Tidy(bool _Built = false)
{if (!_Built || _Ptr == 0)
;
else if (_Refcnt(_Ptr) == 0 || _Refcnt(_Ptr) == _FROZEN) //當(dāng)引用計(jì)數(shù)為0,或者已經(jīng)達(dá)到了最大引用計(jì)數(shù)255
allocator.deallocate(_Ptr - 1, _Res + 2); //釋放字符串
else
--_Refcnt(_Ptr); //引用計(jì)數(shù)減一,此時(shí)并沒(méi)有釋放.
_Ptr = 0, _Len = 0, _Res = 0; }//這時(shí)清空對(duì)象本身
void deallocate(void _FARQ *_P, size_type)
{operator delete(_P); }
0401B90 push ebp
00401B91 mov ebp,esp
00401B93 sub esp,44h
00401B96 push ebx
00401B97 push esi
00401B98 push edi
00401B99 push ecx
00401B9A lea edi,[ebp-44h]
00401B9D mov ecx,11h
00401BA2 mov eax,0CCCCCCCCh
00401BA7 rep stos dword ptr [edi]
00401BA9 pop ecx
00401BAA mov dword ptr [ebp-4],ecx
軟件開發(fā)網(wǎng)
00401BAD mov eax,dword ptr [ebp+8]
00401BB0 push eax
00401BB1 call operator delete (00403210) //這里真正調(diào)用是系統(tǒng)內(nèi)置函數(shù)delete
00401BB6 add esp,4
00401BB9 pop edi
00401BBA pop esi
00401BBB pop ebx
00401BBC add esp,44h
00401BBF cmp ebp,esp
00401BC1 call __chkesp (00409c80)
00401BC6 mov esp,ebp
00401BC8 pop ebp
00401BC9 ret 8
//進(jìn)入delop.cpp 文件的delete方法
void __cdecl operator delete(void *p) _THROW0()
{ // free an allocated object
free(p);
}
//DBGHEAP.C
_CRTIMP void __cdecl free(
void * pUserData
)
{
_free_dbg(pUserData, _NORMAL_BLOCK);
}
軟件開發(fā)網(wǎng)
_CRTIMP void __cdecl _free_dbg(
#endif /* _MT */
void * pUserData,
int nBlockUse
)
{
_CrtMemBlockHeader * pHead;
/* verify heap before freeing */
if (_crtDbgFlag & _CRTDBG_CHECK_ALWAYS_DF)
_ASSERTE(_CrtCheckMemory()); 軟件開發(fā)網(wǎng)
if (pUserData == NULL)
return;
/* forced failure */
if (!(*_pfnAllocHook)(_HOOK_FREE, pUserData, 0, nBlockUse, 0L, NULL, 0))
{
_RPT0(_CRT_WARN, "Client hook free failure.n"); 軟件開發(fā)網(wǎng)
return;
}
/*
* If this ASSERT fails, a bad pointer has been passed in. It may be
* totally bogus, or it may have been allocated from another heap.
* The pointer MUST come from the 'local' heap.
*/
_ASSERTE(_CrtIsValidHeapPointer(pUserData));
/* get a pointer to memory block header */
pHead = pHdr(pUserData);
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
/* if we didn't already check entire heap, at least check this object */
if (!(_crtDbgFlag & _CRTDBG_CHECK_ALWAYS_DF))
{
/* check no-mans-land gaps */
if (!CheckBytes(pHead->gap, _bNoMansLandFill, nNoMansLandSize))
_RPT3(_CRT_ERROR, "DAMAGE: before %hs block (#%d) at 0x%08X.n",
szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)],
pHead->lRequest,
(BYTE *) pbData(pHead));
if (!CheckBytes(pbData(pHead) + pHead->nDataSize, _bNoMansLandFill, nNoMansLandSize))
_RPT3(_CRT_ERROR, "DAMAGE: after %hs block (#%d) at 0x%08X.n",
szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)],
pHead->lRequest,
(BYTE *) pbData(pHead));
}
if (pHead->nBlockUse == _IGNORE_BLOCK)
{
_ASSERTE(pHead->nLine == IGNORE_LINE && pHead->lRequest == IGNORE_REQ);
/* fill the entire block including header with dead-land-fill */
memset(pHead, _bDeadLandFill,
sizeof(_CrtMemBlockHeader) + pHead->nDataSize + nNoMansLandSize);
_free_base(pHead);
return;
}
/* CRT blocks can be freed as NORMAL blocks */
if (pHead->nBlockUse == _CRT_BLOCK && nBlockUse == _NORMAL_BLOCK)
nBlockUse = _CRT_BLOCK;
/* Error if freeing incorrect memory type */
_ASSERTE(pHead->nBlockUse == nBlockUse);
/* keep track of total amount of memory allocated */
_lCurAlloc -= pHead->nDataSize;
/* optionally reclaim memory */
if (!(_crtDbgFlag & _CRTDBG_DELAY_FREE_MEM_DF))
{
/* remove from the linked list */
if (pHead->pBlockHeaderNext)
{
pHead->pBlockHeaderNext->pBlockHeaderPrev = pHead->pBlockHeaderPrev;
}
else
{
_ASSERTE(_pLastBlock == pHead); 軟件開發(fā)網(wǎng)
_pLastBlock = pHead->pBlockHeaderPrev;
}
if (pHead->pBlockHeaderPrev)
{
pHead->pBlockHeaderPrev->pBlockHeaderNext = pHead->pBlockHeaderNext;
}
else
{
_ASSERTE(_pFirstBlock == pHead);
_pFirstBlock = pHead->pBlockHeaderNext;
}
/* fill the entire block including header with dead-land-fill */
memset(pHead, _bDeadLandFill,
sizeof(_CrtMemBlockHeader) + pHead->nDataSize + nNoMansLandSize);
_free_base(pHead); //這里又進(jìn)入了新釋放
}
else
{
pHead->nBlockUse = _FREE_BLOCK;
/* keep memory around as dead space */
memset(pbData(pHead), _bDeadLandFill, pHead->nDataSize);
}
}
//進(jìn)入文件free.c的_free_base函數(shù)
void __cdecl _free_base (void * pBlock)
{
PHEADER pHeader;
if (pBlock == NULL)
return;
if ( __active_heap == __V6_HEAP )
{
#ifdef _MT
_mlock( _HEAP_LOCK );
__try {
#endif /* _MT */
if ((pHeader = __sbh_find_block(pBlock)) != NULL)
__sbh_free_block(pHeader, pBlock);
#ifdef _MT
}
__finally {
_munlock( _HEAP_LOCK );
}
#endif /* _MT */
if (pHeader == NULL)
HeapFree(_crtheap, 0, pBlock);
}
else if ( __active_heap == __V5_HEAP )
{
__old_sbh_region_t *preg;
__old_sbh_page_t * ppage;
__old_page_map_t * pmap;
#ifdef _MT
_mlock(_HEAP_LOCK );
__try {
#endif /* _MT */
if ( (pmap = __old_sbh_find_block(pBlock, &preg, &ppage)) != NULL )
__old_sbh_free_block(preg, ppage, pmap);
#ifdef _MT
}
__finally {
_munlock(_HEAP_LOCK );
}
#endif /* _MT */
軟件開發(fā)網(wǎng)
if (pmap == NULL)
HeapFree(_crtheap, 0, pBlock);
}
else // __active_heap == __SYSTEM_HEAP
HeapFree(_crtheap, 0, pBlock); //最終在這里釋放了堆上分配的內(nèi)存
return;
}
可以看到程序delete時(shí)候三次調(diào)用到allocator.deallocate(_Ptr - 1, _Res + 2);以釋放全部的字符串.
至此,以上的小程序全部結(jié)束.
來(lái)源:與人玫瑰0次