《C++编程艺术》上第二章的代码运行第一个测试程序的时候就报错了,上网找了下,没找到具体的解决方法,CSDN上有网友说是在collect里面出的错。
好吧,我自己动手调进去修改吧。
#include <iostream> #include <new> #include "gc.h" using namespace std; int main() { GCPtr<int> p; try { p = new int; } catch(bad_alloc exc) { cout << "Allocation failure!\n"; return 1; } *p = 88; cout << "Value at p is: " << *p << endl; int k = *p; cout << "k is " << k << endl; system("pause"); return 0; }
在这个函数上单步调试了下,发现到最后return 0那步才引起的中断,看来确实是collect函数出的错。
1 template <class T, int size> 2 bool GCPtr<T, size>::collect() { 3 bool memfreed = false; //是否有内存被释放的标记 4 5 #ifdef DISPLAY 6 cout << "Before garbage collection for "; 7 showlist(); 8 #endif 9 10 list<GCInfo<T> >::iterator p; 11 //这里用两层循环,每次释放了内存后,都要从头对gclist进行再次搜索 12 do { 13 14 // 扫描gclist查找是否有refcount为0的条目,当找到这种条目时 15 // 调用remove函数删除它,remove是STL list类的一个成员 16 for(p = gclist.begin(); p != gclist.end(); p++) { 17 if(p->refcount > 0) 18 continue; 19 20 memfreed = true; 21 22 23 24 // 释放空指向的内存地址 25 if(p->memPtr) { 26 if(p->isArray) { 27 #ifdef DISPLAY 28 cout << "Deleting array of size " 29 << p->arraySize << endl; 30 #endif 31 delete[] p->memPtr; // 释放数组 32 } 33 else { 34 #ifdef DISPLAY 35 cout << "Deleting: " 36 << *(T *) p->memPtr << "\n"; 37 #endif 38 delete p->memPtr; // 释放当个对象 39 } 40 41 } 42 // 从gclist中删除空指向的条目. 43 gclist.remove(*p); 44 45 // 重新搜索 46 break; 47 } 48 49 } while(p != gclist.end()); 50 51 #ifdef DISPLAY 52 cout << "After garbage collection for "; 53 showlist(); 54 #endif 55 56 return memfreed; 57 }
注:上面是修改好的代码
进collect函数后发现,执行gclist.remove(*p); 这步后,后面的p->refcount,p->isArray等信息全错了,突然醒悟过来,
因为这步释放了p节点,而后面还要读取p节点的相关信息,因此导致错误发生。正确的做法是先对p节点进行读取refcount,
isArray等信息,然后释放p中的memptr指针,最后对p节点进行释放。修改好的代码如上所示。