demo_exception.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 259 行
CPP
259 行
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8// demo_exception.cpp// (C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com . // Use, modification and distribution is subject to the Boost Software// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)// Example of safe exception handling for pointer de-serialization// // This example was prepared by Robert Ramey to demonstrate and test // safe exception handling during the de-serialization of pointers in// a non-trivial example.//// Hopefully, this addresses exception issues raised by// Vahan Margaryan who spent considerable time and effort// in the analysis and testing of issues of exception safety // of the serialization library.#include <algorithm>#include <iostream>#include <cstddef> // NULL#include <fstream>#include <string>#include <cstdio> // remove#include <boost/config.hpp>#if defined(BOOST_NO_STDC_NAMESPACE)namespace std{ using ::remove;}#endif#include <boost/archive/tmpdir.hpp>#ifndef BOOST_NO_EXCEPTIONS#include <exception>#endif#include <boost/archive/text_iarchive.hpp>#include <boost/archive/text_oarchive.hpp>#include <boost/serialization/list.hpp>#include <boost/serialization/split_member.hpp>template<class TPTR>struct deleter{ void operator()(TPTR t){ delete t; }};class Course;class Student;class Student{public: static int count; Student(){ count++; } ~Student(){ some_courses.clear(); count--; } std::list<Course *> some_courses;private: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int /* file_version */){ ar & some_courses; }};int Student::count = 0;class Course{public: static int count; Course(){ count++; } ~Course(){ // doesnt delete pointers in list // since it doesn't "own" them some_students.clear(); count--; } std::list<Student *> some_students;private: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int /* file_version */){ ar & some_students; }};int Course::count = 0;class School{public: ~School(){ // must delete all the students because // it "owns" them std::for_each(all_students.begin(), all_students.end(), deleter<Student *>()); all_students.clear(); // as well as courses std::for_each(all_courses.begin(), all_courses.end(), deleter<Course *>()); all_courses.clear(); } std::list<Student *> all_students; std::list<Course *> all_courses;private: friend class boost::serialization::access; BOOST_SERIALIZATION_SPLIT_MEMBER() template<class Archive> void save(Archive & ar, const unsigned int file_version) const; template<class Archive> void load(Archive & ar, const unsigned int file_version);};#if 0// case 1:template<class Archive>void School::serialize(Archive & ar, const unsigned int /* file_version */){ // if an exeception occurs while loading courses // the structure courses may have some courses each // with students ar & all_courses; // while all_students will have no members. ar & all_students; // create students that have no courses // so ~School() will delete all members of courses // but this will NOT delete any students - see above // a memory leak will be the result.}// switching the order of serialization doesn't help in this case// case 2:template<class Archive>void School::serialize(Archive & ar, const unsigned int /* file_version */){ ar & all_students; ar >> all_courses; // create any courses that have no students}#endiftemplate<class Archive>void School::save(Archive & ar, const unsigned int /* file_version */) const { ar << all_students; ar << all_courses;}template<class Archive>void School::load(Archive & ar, const unsigned int /* file_version */){ // if an exeception occurs while loading courses // the structure courses may have some courses each // with students try{ // deserialization of a Course * will in general provoke the // deserialization of Student * which are added to the list of // students for a class. That is, this process will result // in the copying of a pointer. ar >> all_courses; ar >> all_students; // create students that have no courses } catch(std::exception){ // elminate any dangling references all_courses.clear(); all_students.clear(); throw; }}void init(School *school){ Student *bob = new Student(); Student *ted = new Student(); Student *carol = new Student(); Student *alice = new Student(); school->all_students.push_back(bob); school->all_students.push_back(ted); school->all_students.push_back(carol); school->all_students.push_back(alice); Course *math = new Course(); Course *history = new Course(); Course *literature = new Course(); Course *gym = new Course(); school->all_courses.push_back(math); school->all_courses.push_back(history); school->all_courses.push_back(literature); school->all_courses.push_back(gym); bob->some_courses.push_back(math); math->some_students.push_back(bob); bob->some_courses.push_back(literature); literature->some_students.push_back(bob); ted->some_courses.push_back(math); math->some_students.push_back(ted); ted->some_courses.push_back(history); history->some_students.push_back(ted); alice->some_courses.push_back(literature); literature->some_students.push_back(alice); alice->some_courses.push_back(history); history->some_students.push_back(alice); // no students signed up for gym // carol has no courses}void save(const School * const school, const char *filename){ std::ofstream ofile(filename); boost::archive::text_oarchive ar(ofile); ar << school;}void load(School * & school, const char *filename){ std::ifstream ifile(filename); boost::archive::text_iarchive ar(ifile); try{ ar >> school; } catch(std::exception){ // eliminate dangling reference school = NULL; }}int main(int argc, char *argv[]){ std::string filename(boost::archive::tmpdir()); filename += "/demofile.txt"; School *school = new School(); std::cout << "1. student count = " << Student::count << std::endl; std::cout << "2. class count = " << Course::count << std::endl; init(school); std::cout << "3. student count = " << Student::count << std::endl; std::cout << "4. class count = " << Course::count << std::endl; save(school, filename.c_str()); delete school; school = NULL; std::cout << "5. student count = " << Student::count << std::endl; std::cout << "6. class count = " << Course::count << std::endl; load(school, filename.c_str()); std::cout << "7. student count = " << Student::count << std::endl; std::cout << "8. class count = " << Course::count << std::endl; delete school; std::cout << "9. student count = " << Student::count << std::endl; std::cout << "10. class count = " << Course::count << std::endl; std::remove(filename.c_str()); return Student::count + Course::count;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?