提升序列化:指针跟踪如何工作?

时间:2011-08-22 12:39:59

标签: c++ serialization boost

指针跟踪如何在boost序列化中起作用?我用它来序列化系统组件之间的消息,我的印象是我得到了很多不正确的共享对象。是否有可能如果我使用共享指针到我想要序列化的对象,并且新对象恰好具有与之前被删除的对象相同的地址,那么这将被错误地捕获为共享引用?

2 个答案:

答案 0 :(得分:0)

想象一下序列化对象的以下内容:

Example objects for serializing

A开始,使用堆栈确定我们仍需要访问的内容:

  1. 访问A
  2. 推送BC
  3. 弹出并访问C
  4. 按'D'
  5. 其他东西删除B并用D
  6. 替换它
  7. 弹出并访问'D'
  8. 弹出并访问标记为B的内容,但现在真的是D
  9. 然后您的情况将被错误地捕获为共享引用。如果任何可以更改指针的任何,或者它们指向序列化开始和结束之间的对象,那么你将得到一个不一致的状态。

答案 1 :(得分:0)

简短回答:是的,这种情况发生了。

原因是(可以从其他答案和评论中得出结论),这是对序列化库的意图的轻微滥用。因此,如果使用boost序列化来记录一天中的对象(例如,在序列化开始时并非所有对象都在内存中),并且对象碰巧具有相同的地址,则它们将被错误地共享。这发生在共享指针上,也发生在常规指针上(据我所知)。

要解决此问题,请先避开指针,或关闭跟踪功能。如果你关闭跟踪,仍然序列化共享指针(我现在这样做,虽然这可能不太理想),在boost中的几个硬编码检查会抱怨跟踪被关闭。为了解决这个问题,我修改了boost头的本地副本(并且必须在每次更新和用于编译的系统上执行此操作)(虽然这很简单,编译器指向正确的行并且它们已清楚地记录在案) 。如果你可以选择在没有指针的情况下工作,那么你就不用担心这个问题了。

除此之外,日志记录工作非常出色,因此请不要将boost序列化用于此目的(如上面的一些评论所示)。

要在对象到达时记录对象,只需使用void Log(Msg* msg) {ar & NVP(msg);}并按以下方式读取它们:

Msg* Read() {
    Msg* msg(0); 
    try {ar & NVP(msg);}
    catch (boost::archive::archive_exception const&) { }
    return msg; 
}

你会调用上面的Read函数,直到返回的指针是一个NULL指针,然后你知道日志已经完成。