当前位置:首页 > 工业控制 > 电子设计自动化
[导读]基本类型和变量. 像其他高级语言一样,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结尾的文件,而现在的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机制更复杂,主要就是他定义了一组权限规则,private,protected,public.(记得类后面有;号啊)struct内部的成员都是public属性.

C++标准库(STL)

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

现在我们来玩玩string这个东东.这个东东在pascal里也有,内存分配是 引用计数 +Length + ansichar*,在string里,在C++里只知道是一个常用对象,具体怎么分配的,网上好多垃圾也没有说清楚.只说什么copyonwrite乱七八糟之云乎.既然是类,那么就要遵循C++实例规则.C++没有pascal那么严格,pascal里只有明确的create才能创造对象,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);用另一个字符串的一节去构造

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(); //实现了迭代器算法

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

软件开发网

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还重载了许多符号,比如*,-,+等,以实现简单快捷安全的访问元素.

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

//下面是他的具体实现

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的内存实现,很简单并且引用了_Refcnt机制,这个机制可以帮助我们实现copy_on_write.

但是可以明显看到,这点也给我们带来了麻烦.在多线程编程中,_Refcnt很容易被破坏,造成内存错误或者内存泄漏.

这点应该向pascal学习了,delphi的string增加了锁机制,所以可以很好在多线程使用.

struct char_traits<E> { //一个基本操作类模板,可以看出里面全部都是静态成员函数,

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

};

软件开发网

以上可以看了,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; 软件开发网

iterator begin(); //实现了迭代器

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(); //构造函数 软件开发网

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;

}; 软件开发网

具体iterator实现

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只有四个成员元素,第一个对象分配器,接下来的三个,其实都是一个普通指针而已. 软件开发网

依次分析,其实所谓的iterator的*,+,-操作都是C++编译器的内置的指针操作而已.

另外上面的可以看出,上面的每个类都定义了好多const操作.其实const既可以定义变量,也可以定义类成员函数(此时放在类的成员函数后面).

当const修饰变量的时候,表明此变量不能修改.当const修改类成员函数,表明此函数不能修改类的成员元素.

上面只了解了几个常用的标准库,还有很多类似的库.

软件开发网

下面介绍下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 软件开发网

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

软件开发网

/* 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; 软件开发网

/* 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)) //这里进入系统给出的函数_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;

软件开发网

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

软件开发网

/* 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 软件开发网

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函数,没有内核符号,不能再跟踪了.

}

软件开发网

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;

}

软件开发网

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

软件开发网

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

00401BB0 push eax

00401BB1 call operator delete (00403210) //这里真正调用是系统内置函数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);

}

软件开发网

_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()); 软件开发网

if (pUserData == NULL)

return;

/* forced failure */

if (!(*_pfnAllocHook)(_HOOK_FREE, pUserData, 0, nBlockUse, 0L, NULL, 0))

{

_RPT0(_CRT_WARN, "Client hook free failure.n"); 软件开发网

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); 软件开发网

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

软件开发网

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次

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭