【问题标题】:boost text deserialization crashing on 32bit windows machine提升文本反序列化在 32 位 Windows 机器上崩溃
【发布时间】:2015-05-24 16:24:06
【问题描述】:

我使用 FLTK 创建了一个多平台应用程序,它使用 boost 文本序列化功能来实现可移植的跨平台文档保存功能。 (如果这是个坏主意:恐怕为时已晚!)。

这在 Mac 和我编译它的 Windows 机器上运行良好。然而,我在较低规格的 Windows 机器上使用了编译后的二进制文件,虽然它在所有其他功能上运行良好,但在打开保存文件时(即反序列化时)程序会崩溃。

查看配置较低的 Windows 机器上的任务管理器和活动监视器中的内存使用情况,我注意到了这种不同的行为

Windows:内存使用是问题所在,它一直在攀升,直到程序使用大约 800Mb 的 RAM,然后程序崩溃

Mac:在反序列化完全相同的文件时,相同编译代码的内存使用量最高为 40Mb。

Windows 二进制文件是 Win32(32 位),我已经验证了在 64 位和 32 位 Mac 版本中相同的正常工作行为。所有代码都使用静态库链接(除非不可能,例如 Mac OS 中的 CRT)。

为什么要使用 完全相同的代码 使用自包含在仅头文件中的 boost 功能会导致 Windows 机器上这种任性的内存使用(它在更高规格的机器上运行良好,尽管我没有跟踪内存使用)而所有其他程序功能都可以正常工作?

我能做些什么呢?

谢谢。

【问题讨论】:

  • 为了缩小问题的范围,您是否尝试过一个简单的控制台程序来测试类似于您在 GUI 版本中编写的 boost 序列化。它还会泄漏内存吗?

标签: c++ serialization boost fltk


【解决方案1】:

我怀疑使用的类型根本不一样。

例如在 32 位编译器(或 目标架构,真的)上,long 通常是 32 位(4 字节)。

在 64 位编译器上,long 通常是该大小的两倍。即使您使用了文本表示,这也会让您感到困惑。

考虑当读取的数字超过int32_t 容量时会发生什么。它可能会导致一个很大的负数。现在,将其解释为size_t,您将得到破坏:它将导致更大的大小,并且如果代码进行分配以匹配...

所以,第一件事:

  1. 检查所有您的数据类型以查看它们是否独立于体系结构。例如。使用

    #include <cstdint>
    

    拼写或您的类型,例如int32_tuint64_t。永远不要依赖默认值。

  2. 完成后,考虑使用此处的 EPA 便携式存档实现:https://epa.codeplex.com/

    这是专为便携而设计的二进制存档。我希望这可以为您提供所有涉及的类型/大小的编译时验证。

【讨论】:

  • 这两点都很好,谢谢,但目前还不能实现/测试。只是检查一下,在更高规格的机器上运行的 Windows 版本 是为 32 位目标架构编译的,所以我有点不清楚为什么 32 位版本只会在 32 位机器上失败?除此之外,鉴于我想要可移植性,我是否应该将所有内容都更改为 int32_t(而不是 int64_t)?
  • int64_t 是 32 位系统上完全有效的类型。它可能只是效率不高,因为它超出了本机寄存器的大小。然而,当然,应用领域规定了所需的整数值范围。这台机器根本不会出现这种情况。那将是优化。记住what they say about premature optimization
  • 我正在用 int32_t 替换所有内容,但我对此表示怀疑,因为文本序列化与更改前相同。我想我没有说清楚:较低规格的 32 位机器上的崩溃使用与较高规格的 64 位机器上相同的二进制/可执行文件。它是在更高规格的机器上编译的,但用于 32 位架构。我看不出错误的类型会如何导致相同的可执行文件在一个文件上崩溃,但在另一个文件上却没有。我错过了什么吗?
  • 嗯嗯。也许只是堆溢出......我想你会注意到这一点,就内存使用而言
  • 如果这就是你的意思,在此之前我没有看到任何任性的内存问题。
猜你喜欢
  • 2012-08-26
  • 1970-01-01
  • 1970-01-01
  • 2014-03-23
  • 2012-04-17
  • 1970-01-01
  • 2011-03-18
  • 2015-08-18
  • 1970-01-01
相关资源
最近更新 更多