ISO C++基本类型和变量

时间:2009-08-04

  基本类型和变量.

  像其他语言一样,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);以释放全部的字符串.

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



  
上一篇:高效的统一无线交换网络架构
下一篇:LED控制系统技术

免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

相关技术资料