C++的永久对象存储(3)_C/C++语言_黑客防线网安服务器维护基地--Powered by WWW.RONGSEN.COM.CN

C++的永久对象存储(3)

作者:黑客防线网安C/C++教程基地 来源:黑客防线网安C/C++教程基地 浏览次数:0

本篇关键词:存储对象永久POST
黑客防线网安网讯:  在T-tree中插入和删除稍微复杂一些。对于插入操作,首先使用上面的搜索过程来查找约束插入关键值的节点。如果存在这样的节点,那么节点中有空余的话关键值被插入到这个节点中。如果节点...
  在T-tree中插入和删除稍微复杂一些对于插入操作首先使用上面的搜索过程来查找约束插入关键值的节点如果存在这样的节点那么节点中有空余的话关键值被插入到这个节点中。如果节点中没有空余,那么关键值被插入到节点中,该节点的最左关键值被插入到该节点的左子树中(如果左子树为空,就分配一个新的节点把最左关键值插入)。如果没有发现约束节点,那我们用N来表示搜索失败的最后遇到的节点并按下述步骤继续:如果N有空余,那么关键值就插入到N中;否则,关键值将被插入到一个新节点并根据关键值以及最左关键值和最右关键值作为N的右或左子节点/树。
删除关键值从判定包含关键值的节点开始,并从节点中删除关键值。如果删除关键值后剩下一个空的叶结点,那么节点也被删除。如果删除后剩下一个内部节点或者不完全叶其中包含比最小数量少的关键值,那么不足的将通过移动左子树中最大的关键值到节点中或者合并节点和右子树来补充。
无论插入还是删除,分配/释放节点可能导致树不平衡和进行旋转操作(RR, RL, LL, LR)。(下面的描述中子树的高度包括了插入和删除的影响。)在插入情况下,检查沿着新分配节点开始的节点到根节点的节点直到
发现一个节点有两个等高的子树(在这种情况下不需要旋转了),或者 发现一个节点的左子树和右子树有大于1的不同高度并执行包含节点的单一旋转。
  在删除情况下,检查沿着释放节点的父母开始到根节点的节点直到发现一个节点它的子树高度相差1。而且每一次遇到一个节点的子树的高度相差大于1时,进行一次旋转。注意释放一个节点可能导致多次旋转。
有几个测试程序来测试 POST++ 持久类库中的类,他们被包含在缺省的make目标中:
ProgramTested classestesttree.cxxAVL-tree, l2-node, hash tabletesttext.cxxtext, stringtestspat.cxxrectangle, R-tree, hash tabletestperf.cxxT-tree insert, find and remove operations
和POST++一起使用STL类
从 POST++ 存储器中保存和取得STL类是可能的。POST++ 提供了特别的STL分配子并重载了new/delete操作符来保持STL对象。有几个使得STL持久的模型,通过以下几个宏来控制:
USE_MICROSOFT_STL 使用 Microsoft STL 类,随 Microsoft Visual C++ 一起附带。这个类库和C++ STL 标准不完全兼容。 USE_STD_ALLOCATORS 使用和C++标准中一样的分配子。分配子对象包含在STL对象中,分配子对象中的实例方法用于分配/释放空间。所以有可能执行一个“聪明的”分配子:仅在对象包含这个分配子的情况下分配子才为 POST++ 存储器中的对象分配空间而且这个分配子也放在存储器中。否则,对象所占空间将通过标准 malloc() 函数这个正常途径来分配。这个选项可以和 SGI STL 库以及 Microsoft STL 库一起使用。注意顺从标准的 SGI STL 分配子使用了许多没有广泛实现的语言特性。特别是,他们依赖于成员模板,局部特殊化,局部分类(排序)的方法模板,typename 关键字,以及使用 template 关键字来引用依赖类型的模板成员。所以在指定这个宏定义时只有少数 C++ 编译器可以编译 SGI STL 库。如果没有设置这个宏,那么 POST 提供一个含有静态成员函数的分配子并且所有对象都从 POST++ 存储器中分配。使用这个分配子的应用一次只能打开一个POST++ 存储器。 REDEFINE_DEFAULT_ALLOCATOR 有两个途径使得 STL 对象持久,一个途径是引入新类型:
typedef basic_string<char, char_traits<char>, post_alloc<char> > post_string;
另外一个途径是使所有类具有持久能力。当定义了 REDEFINE_DEFAULT_ALLOCATOR 宏,任何 STL 类可以在 POST++ 存储器中分配。为了在持久存储器中创建新对象,你必须指定存储器作为 new 操作符额外的参数。如果存储器被忽略,那么对象将使用标准 malloc() 函数。
  POST++ 到 STL 的接口不需要任何 STL 类的改变,所以你可以使用你想执行的任何 STL。但是作为一个结果,STL类不包含类型描述所以 POST++ 没有STL 对象的格式信息。所以 POST++ 不能够进行垃圾收集和引用对齐。当使用了 STL 接口时,POST++ 存储器必须始终镜像到相同的虚拟地址上。如果你传递 storage::fixed 标志到 storage::open(int flags) 方法,那么如果不能镜像存储器到相同的内存地址 POST++ 将报告错误并且返回 false。如果你的应用只使用了一个存储器并且不镜像其他对象到虚拟内存中,那么几乎所有的操作下都可能镜像存储器到相同的内存地址。
POST++ 到 STL 库的接口定义在在头文件 post_stl.h 中。这个文件必须包含在任何 STL 包含文件中。同样宏 REDEFINE_DEFAULT_ALLOCATOR,USE_STD_ALLOCATORS 以及 USE_MICROSOFT_STL 被在 post_stl.h 之前定义。
POST++ 包含使用 STL++ 类的例子 stltest.cxx。这个例子使用两个 STL 类 - string 和 vector。从标准输入读进来的行被压入到 vector 中并且程序被再次启动所有的vector的元素被打印到标准输出上。这个例子被包含在为 Microsoft Visual C++ 配置的 makefile 的缺省目标中(其使用VC 中附带的 Microsoft STL 类)。你也可以尝试用其他版本的 STL 库来构建这个测试但是不要忘记关于 REDEFINE_DEFAULT_ALLOCATOR 和 USE_STD_ALLOCATORS 宏。这个例子同样可以和 SGI STLport 3.12 以及 GCC 2.8.1 一起测试。
替换标准分配子
在前面一节中我解释了如何和 STL 库一起使用 POST++。但是仍然有很多其他你想用的C++和C库以及应用,而且没有提供象 STL 这种易通融的分配机制。在这种情况下唯一可能的解决方案(如果你不想改变此库的任何源代码的话)就是用一个 POST++ 提供的来替换标准的分配机制。这样任何动态分配对象都从 POST++ 存储器中分配(除了一个不能在这种情况下使用的存储器)。
POST++ 发行包中包含的文件 postnew.cxx 重定义了标准的 malloc,free,realloc 和 calloc 函数。当打开存储器时,所有的对象被在存储器中分配。否则 sbrk() 函数被用来分配对象(为这些对象分配的空间没有回收)。可能不需要接触这些标准C分配函数而仅需重载缺省的C++操作符 new 和 delete。当编译 postnew.cxx 时定义 DO_NOT_REDEFINE_MALLOC 宏来这么做。从 postnew.cxx 生成的目标文件必须在标准C库前传递给链接程序。
作为一个 POST++ 这样使用的例子可以参见 testnew.cxx 和 testqt.cxx。第一个举例说明了标准C++数组如何持久化。第二个举例说明了POST++如何和Qt类库一起工作。
就 POST++ 没有关于存储类的格式信息这里有一些限制在 POST++ 的使用上:
包含虚函数的类不被支持(POST++ 不能正确的初始化到虚函数表的指针)。 隐式内存释放(垃圾收集器)是不可能的 - POST++ 没有关于对象内部指针位置的信息。 存储器必须总映射到相同的虚拟地址上因为如果基地址改变了 POST++ 不能调整指针。
如果所有这些限制不是你的应用所必需的,你可以使其持久化而不需要任何代码的改动。这个方法在C和C++程序中都可以使用。
如何使用 POST++
这里有几个 POST++ 类和应用的例子。其中最简单的就是游戏“猜动物”。这个游戏的算法非常简单并且结果看起来给人以深刻的印象(有些象人工智能)。此外这个游戏是一个非常好的例子,阐明了持久对象存储的好处。这个游戏的源代码在文件 guess.cxx 中。创建这个游戏包含在缺省的make目标中。执行guess来运行它。
Unix specific: 当你准备和 POST++ 库链接你的Unix应用并且持久对象中波阿含虚函数,请不要忘记重编译 comptime.cxx 文件并包含在链接列表中。这个文件是必须的用于 POST++ 提供可执行文件的时间戳,被放在存储器中用来判定什么时候应用被改变并在需要的时候重新初始化对象内的虚函数表。Attention! 这个文件必须在你每次重新链接你的应用时被重新编译。我建议你让编译器为你调用链接程序并包含 comptime.cxx 源文件在为运行映像目标文件提供的对象文件列表中(see makefile)。
调试 POST++ 应用的细节
这一节的内容对使用了事务的应用是非常有意义的。POST++ 使用页面保护机制来提供当源页面修改时生成影子页面,当存储器打开或事务提交时所有文件页面的映像是只读保护的。所以任何试图修改分配在这些页面里对象的内容将导致一个访问违例异常。这个异常被指定的 POST++ 句柄处理。但是如果你使用调试器,它将首先捕获这个异常并停止应用程序。如果你想调试你的应用你必须作一些准备:
在 Unix 可以充分的告诉调试器不要捕获 SIGSEGV 信号。比如对于 GDB 它可以通过命令来完成:handle SIGSEGV nostop noprint pass。如果 SIGSEGV 信号不是由存储页面保护违例产生,但是是程序中的一个错误,POST++ 异常处理程序将“理解”它不是自己的异常并送出一个 SIGABRT 信号到己进程中,这可以被调试器捕获。 在 Windows POST++ 使用不处理异常过滤器来( Unhandled Exception Filter )处理存储器页面保护违例。不幸的是不可能让 Microsoft Debugger 忽略不处理异常。如果你准备调试你的应用,你必须把所有你的程序代码(main 或者 WinMain 函数)封装为结构化的异常阻塞。你必须在 Borland C++ 中总使用结构化异常处理,因为 Unhandled Exception Filter 没有在Borland中被正确调用。请使用两个宏 SEN_TRY 和 SEN_ACCESS_VIOLATION_HANDLER() 来封装 main(或 WinMain)的函数体:
main() { SEN_TRY { … } SEN_ACCESS_VIOLATION_HANDLER(); return 0; }
请确定调试器对此异常的行为是“如果没有处理就停止”而不是“总是停止”(你可以在 Debug/Exceptions 菜单中检查它)。在文件 testrans.cxx 中你可以发现使用结构化异常处理的例子。
关于 POST++ 的更多的一些信息
POST++ 是 freeware。开发出她希望是有用的。通过她你可以做任何你想做的(在开发产品中使用 POST++ 没有任何限制)。我将很高兴来帮助你使用 POST++ 和得到关于 POST++ 任何类型的信息(错误报告,建议…)。POST++ 的免费软件情形并不意味着缺少支持。我保证将努力修正任何报告的错误。也提供 e-mail 支持。POST++ 有几种用途:在不同期间保存信息,在文件中保存对象系统,快照, 信息系统… 但是如果你感到你需要在你的应用使用更重要的面向对象数据库以提供并发,分布式以及事务处理,请访问 GOODS (Generic Object Oriented Database System) home page。
    黑客防线网安服务器维护方案本篇连接:http://www.rongsen.com.cn/show-15367-1.html
网站维护教程更新时间:2012-04-04 22:53:52  【打印此页】  【关闭
我要申请本站N点 | 黑客防线官网 |  
专业服务器维护及网站维护手工安全搭建环境,网站安全加固服务。黑客防线网安服务器维护基地招商进行中!QQ:29769479

footer  footer  footer  footer