當(dāng)前位置:首頁(yè) > 工業(yè)控制 > 電子設(shè)計(jì)自動(dòng)化
[導(dǎo)讀]基本類型和變量. 像其他高級(jí)語(yǔ)言一樣,ISO C++除了像C一樣,有自己的基本類型:字符型,整形,浮點(diǎn)型等,還提供了可用于自定義類型機(jī)制.所謂的C++ STL,正是這個(gè)機(jī)制定義了大量的類型和操作. 比如可變長(zhǎng)的string,vector等.一

基本類型和變量.

像其他高級(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次

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉