www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

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

基本類型和變量.

像其他高級語言一樣,ISO C++除了像C一樣,有自己的基本類型:字符型,整形,浮點型等,還提供了可用于自定義類型機制.所謂的C++ STL,正是這個機制定義了大量的類型和操作.

比如可變長的string,vector等.一般和C一樣,也是為了兼容C,內置類型一般小寫.

對于所謂內置類型不同,一般指位數不同而已,比如int 16(當然這個有爭議,很多語言都是32位,所以C++又定義了一個long 32)和float(32位),當然也有不同的類型位數一樣,比如剛才int 和 short都是16.

其實所有的這一切都是編譯器想怎么解釋就怎么解釋(也有標準的約束).

像C語言一樣,C++的字符用單引號,字符串用雙引號,這點和pascal不同,pascal都用單引號,編譯器自行解釋.另外,和pascal不同的是,C++/C定義常量,也用特殊標識,比如字符串前加"L"代表unicode串,整形后加L表示long型,也就是32位的.

與C一樣,都用""作轉義字符.整形和字符型在一定范圍兼容.

作用域:C++比C多了名字空間作用域,類作用域(其實C也有struct作用域).

頭文件,C直接用.h結尾的文件,而現(xiàn)在的C++頭文件一般都不帶.h,比如 #include <string> #include <string.h>,前者定義有string類型,而后者則是一些char *處理函數.

C/C++都有特殊類型,引用(符號&), 引用其實就是一個變量的別名,僅此而已.像const變量一樣,引用必須初始化. 如:int i; int &reint = i;正因為引用是別名,所以不能直接對其賦值,&reint = i;(error).

枚舉類型:其實就是定義一些常量的集合.關鍵字enum mode {input,output,append};枚舉類型都有默認的值,從第一個為0開始,后面依次加1,input = 0,output = 1,append =2.當然也可以給定其初始化值.enum mode {input = 1,output,append};

像C一樣,關鍵字typedef可以定義復雜的類型.比如typedef void (Message_Process::*FN_Msg)(Message*); FN_Msg為函數指針類型,可以用其定義其他的變量,比如FN_Msg p = NULL;

與C不同的是,C++有class關鍵字.標準庫通過他,定義大量的數據類型,比如string,istream,ostream等等.雖然class和 struct差不多,但class機制更復雜,主要就是他定義了一組權限規(guī)則,private,protected,public.(記得類后面有;號啊)struct內部的成員都是public屬性.

C++標準庫(STL)

首先名字空間using namespace std; 當然也可以直接using std::cin;

現(xiàn)在我們來玩玩string這個東東.這個東東在pascal里也有,內存分配是 引用計數 +Length + ansichar*,在string里,在C++里只知道是一個常用對象,具體怎么分配的,網上好多垃圾也沒有說清楚.只說什么copyonwrite亂七八糟之云乎.既然是類,那么就要遵循C++實例規(guī)則.C++沒有pascal那么嚴格,pascal里只有明確的create才能創(chuàng)造對象,C++到處都暗藏殺機.很多隱式定義.

string定義(四種):

string s1;

string s2(s1);//定義并初始化

string s3("value");//常量初始化

string s4(n,'c');//相同字符常量初始化

運算符重載(+,=(賦值),==,!=,>,<等等)

成員函數size和empty判斷長度.

string::size_type類型

template<class E, //定義模板類,泛型化

class T = char_traits<E>, //T,A也一個泛型實例的類

class A = allocator<T> > //泛型類

class basic_string {

public:

typedef T traits_type; //定義泛型類型

typedef A allocator_type;

typedef T::char_type char_type; //這里A和T只是一個類域而已

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;

//隱式構造函數 ,以下都是其構造函數

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);用另一個字符串的一節(jié)去構造

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種構造函數

const A& al = A());

basic_string& operator=(const basic_string& rhs); //賦值運算符重載

basic_string& operator=(const E *s);

basic_string& operator=(E c); //三種賦值運算

iterator begin(); //實現(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; //下標重載

reference operator[](size_type pos);

const E *c_str() const; //返回c格式的字符串函數

const E *data() const; //.

size_type length() const; //長度大小操作

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ā)網

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(迭代器)

他的存在主要是為了集合數據的安全訪問.也是提供一些遍歷的方法.

begin和end操作.返回一個iterator.

vector<int>::iterator iter = ivec.begin();//返回容器的第一個元素iterator.

iterator還重載了許多符號,比如*,-,+等,以實現(xiàn)簡單快捷安全的訪問元素.

*iter = 0;//對當前元素賦值.

這里值得一提的是,當容器的元素增加,刪除,或交換,該容器的iterator將失效,得重新檢索得到iterator.

template<class C, class T, class Dist = ptrdiff_t> //ptrdiff_t是一個run-time library定義的類型

struct iterator { //可以看iterator是一個沒有任何操作的模板結構.

typedef C iterator_category;

typedef T value_type;

typedef Dist distance_type;

};

而真正的具體定義卻也只是像下面這樣一句話而已.

typedef _A::pointer iterator;

typedef _A::const_pointer const_iterator;

//下面是他的具體實現(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]); } //返回字符串內存中的前面一個字符

void _Freeze()

{if (_Ptr != 0

&& _Refcnt(_Ptr) != 0 && _Refcnt(_Ptr) != _FROZEN)

_Grow(_Len);

if (_Ptr != 0)

_Refcnt(_Ptr) = _FROZEN; }

_E *_Ptr;//而_E此時是char,即指向string的首個字符

_E *_Ptr;

size_type _Len, _Res;

//真正的字符串只存儲_Refcnt和char array[_Len]數組.

//從這上面可以看出,string對象內存只存儲三個變量,第一個首字母指針,

//第二個是長度,第三個應該最大長度.因為string是一個可自動加長的類型.

可以看出,string的內存實現(xiàn),很簡單并且引用了_Refcnt機制,這個機制可以幫助我們實現(xiàn)copy_on_write.

但是可以明顯看到,這點也給我們帶來了麻煩.在多線程編程中,_Refcnt很容易被破壞,造成內存錯誤或者內存泄漏.

這點應該向pascal學習了,delphi的string增加了鎖機制,所以可以很好在多線程使用.

struct char_traits<E> { //一個基本操作類模板,可以看出里面全部都是靜態(tài)成員函數,

typedef E char_type; //所以只給其他類用,不實例對象

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ā)網

以上可以看了,basic_string并沒有重載一些常用的運算符,但實際我們又經??梢杂玫?比如 +,>,<,==等等

即沒有像下面的

bool basic_string::operator<(const basic_string &rhs);

basic_string& basic_string::operator+(const basic_string &rhs);

等等,其實我猜測應該是編譯器,把這些自行的解釋了,比如<就用compare操作代替.當然我對C++沒有什么深入研究的,只是猜測.

typedef basic_string<char> string;//這就是真正的string的全部,就一句話.表明它是操作char 的東東.

vector類型(不像string,而是一個類模板.)

同一類型對象的組合,像基本類型數組,我們稱之為"容器".vector本身并不是直接類,也就是不能直接使用,在經過模板實例化.

vector也有好幾種構造函數.

vector<T> v1; //構造空的vector對象.

vector<T> v2(v1); //將v1作副本構造一個vector對象.

vector<T> v3(n,i); //包含n個值為i的元素vector對象.

vector<T> v4(n); //包含n個值為初始化的元素的vector對象.

vector用引用對象初始化的時候,要保持兼容性.

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; //這里定義一個迭代器.

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的四個構造函數

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ā)網

iterator begin(); //實現(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); //下標操作

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; //包含一個對象分配器

};

template<class T>

class allocator { //對象分配器

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(); //構造函數 軟件開發(fā)網

allocator<T>& operator=(const allocator<T>); //基本的賦值運算

pointer allocate(size_type n, const void *hint);

void deallocate(pointer p, size_type n); //釋放對象

void construct(pointer p, const T& val); //構造內存對象

void destroy(pointer p); //釋放指針

size_type max_size() const;

}; 軟件開發(fā)網

具體iterator實現(xiàn)

typedef _A::pointer _Tptr; //普通指針

typedef _A::const_pointer _Ctptr; //這時僅僅是一個常指針類型

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只有四個成員元素,第一個對象分配器,接下來的三個,其實都是一個普通指針而已. 軟件開發(fā)網

依次分析,其實所謂的iterator的*,+,-操作都是C++編譯器的內置的指針操作而已.

另外上面的可以看出,上面的每個類都定義了好多const操作.其實const既可以定義變量,也可以定義類成員函數(此時放在類的成員函數后面).

當const修飾變量的時候,表明此變量不能修改.當const修改類成員函數,表明此函數不能修改類的成員元素.

上面只了解了幾個常用的標準庫,還有很多類似的庫.

軟件開發(fā)網

下面介紹下new和delete關鍵字.

#include <iostream>

#include <string>

using namespace std;

int main(void)

{

int i;

string *psa = new string[3]; //這里下斷點以跟蹤

for (i=0;i<3;i++) {

psa[i] = "huzg";

}

for (i=0;i<3;i++) {

cout << psa[i] <<endl;

}

delete [] (psa); //這里調用了vector deleting destructor.

return 0;

}

9: string *psa = new string[3];

0040126D push 34h //這里其實是實際大小,34h=52

0040126F call operator new (00409840) //這里調用C++編譯器內置函數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ā)網

0040985B ret

--- No source file -----------------------

0040985C int 3

0040985D int 3

0040985E int 3

0040985F int 3

//CRT內new的源碼new.cpp

void * operator new( unsigned int cb )

{

void *res = _nh_malloc( cb, 1 );

return res;

}

//_nh_malloc又進入了DbgHeap.c文件里

void * __cdecl _nh_malloc (

size_t nSize,

int nhFlag

)

{

return _nh_malloc_dbg(nSize, nhFlag, _NORMAL_BLOCK, NULL, 0);

}

//此函數是__cdecl,和__stdcall一樣都是從右到左壓棧,但__cdecl棧是調用者來維護,也就是調用它函數清棧,__stdcall則是函數自己來維護.

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ā)網

/* 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ā)網

/* 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)) //這里進入系統(tǒng)給出的函數_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); //進入_heap_alloc_base

if (pHead == NULL)

return NULL;

軟件開發(fā)網

/* 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ā)網

/* 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);

}

//進入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ā)網

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 );//最終走到這里,直接調用ntdll里的HeapAlloc函數,沒有內核符號,不能再跟蹤了.

}

軟件開發(fā)網

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ā)網

/* 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;

//這里應該調用了basic_string析構函數,而basic_string析構函數只有一個:~basic_string(){_Tidy(true); }

具體調用如下:

std::basic_string<char,std::char_traits<char>,std::allocator<char> >::`vector deleting destructor':

00401419 call `eh vector destructor iterator' (00409db0)

//最后再調用basic_string析構函數

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) //當引用計數為0,或者已經達到了最大引用計數255

allocator.deallocate(_Ptr - 1, _Res + 2); //釋放字符串

else

--_Refcnt(_Ptr); //引用計數減一,此時并沒有釋放.

_Ptr = 0, _Len = 0, _Res = 0; }//這時清空對象本身

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ā)網

00401BAD mov eax,dword ptr [ebp+8]

00401BB0 push eax

00401BB1 call operator delete (00403210) //這里真正調用是系統(tǒng)內置函數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

//進入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ā)網

_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ā)網

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ā)網

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ā)網

_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); //這里又進入了新釋放

}

else

{

pHead->nBlockUse = _FREE_BLOCK;

/* keep memory around as dead space */

memset(pbData(pHead), _bDeadLandFill, pHead->nDataSize);

}

}

//進入文件free.c的_free_base函數

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ā)網

if (pmap == NULL)

HeapFree(_crtheap, 0, pBlock);

}

else // __active_heap == __SYSTEM_HEAP

HeapFree(_crtheap, 0, pBlock); //最終在這里釋放了堆上分配的內存

return;

}

可以看到程序delete時候三次調用到allocator.deallocate(_Ptr - 1, _Res + 2);以釋放全部的字符串.

至此,以上的小程序全部結束.



來源:與人玫瑰0次

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

C語言是一種高級程序設計語言,它提供了十分完備的規(guī)范化流程控制結構。因此采用C51語言設計單片機應用系統(tǒng)程序時,首先要盡可能地采用結構化的程序設計方法,這樣可使整個應用系統(tǒng)程序結構清晰,易于調試和維護。對于一個較大的程序...

關鍵字: C51語言 變量 存儲

定義一個變量,就是在內存中為你定義的這個變量開辟一段內存空間,如果這個變量沒有初始化,那么系統(tǒng)會隨機給這個變量賦一個值,這個值我一般稱它為"垃圾數"。沒有初始化的變量我認為它是沒有意義的,是在浪費內存,就比如人剛出生的時...

關鍵字: 變量 初始化 賦值

用靜態(tài)局部變量,還是臨時變量,要牽涉到你項目具體情況,比如:RAM資源、代碼運行效率等。(臨時變量還會有一個數據拷貝過程)所以,該如何分配堆棧,該用靜態(tài)還是臨時變量,需要綜合考慮你項目的情況而定。

關鍵字: 靜態(tài)局部 變量 項目

服務器編程中一塊是定時器,影響著服務器性能 定時器一個作用是用于定時檢測客戶端連接,并踢掉非活動連接; 定時器一般會把定時事件封裝成定時器,并進行組織以方便管理

關鍵字: 定時器 類型

電阻的封裝規(guī)格

關鍵字: 封裝 類型

步進電機是將電脈沖信號轉變?yōu)榻俏灰苹蚓€位移的開環(huán)控制元件。在非超載的情況下,電機的轉速、停止的位置只取決于控制脈沖信號的頻率和脈沖數。

關鍵字: 步進電機 類型 辨別

在C語言中,按照生命周期來分,變量只有兩類:靜態(tài)變量和動態(tài)變量。

關鍵字: C語言 變量

為增進大家對顯卡的認識,本文將基于兩點介紹顯卡:1.顯卡有哪些類型?2.顯卡插槽有哪些?

關鍵字: 顯卡 指數 類型

Windows 10 2020年10月更新上線了! 經過幾個月的Insider測試,2020年10月更新,即20H2版本面向公眾上線。和之前的版本一樣,這將是一個分階段推出的版本,也就是說并不是每個人都能同時得到它。不過...

關鍵字: iso windows10

在往期文章中,小編對工業(yè)以太網有過諸多介紹。本文中,小編將對工業(yè)以太網的6大類型加以闡述。如果你對工業(yè)以太網具有興趣,不妨繼續(xù)往下閱讀哦。

關鍵字: 工業(yè)以太網 指數 類型
關閉