【问题标题】:Wrapping a string buffer包装字符串缓冲区
【发布时间】:2012-07-11 11:38:20
【问题描述】:

我们有一个大型 C++ 实时程序,它使用不同大小的缓冲区(例如 char str[500])来存储字符串。

由于过去发生了一些内存泄漏,我们希望使用 MyString 类包装字符串,该类将使用缓冲区和大小进行初始化。

问题在于如何高效、轻松地同时分配缓冲区和包装器,同时保持缓冲区作为类的一部分分配,而不是从堆中分配(参见下一个示例)。

我尝试过以下方式使用模板:

template <unsigned int N>
class BufferString : public MyString
{
public:
   BufferString() : MyString(m_buf, N) { }
   char m_buf[N];
};

所以它可以分配为类成员或自动变量:

class SomeClass
{
   BufferString<500> m_str;   // Need the buffer to be allocated in SomeClass
};

void foo()
{
   BufferString<350> str;     // Need the buffer to be allocated on the stack
}

但是,使用此解决方案,可执行文件的大小会急剧增加,每次模板实例化大约 1kB(可能是由于构造函数的编译)。

有没有更好的方法来做到这一点?

谢谢。


编辑:我找到了一个类似于我提出的解决方案的实现,称为 fixed_char_buf(由 John Panzer,发现 here)。

这个方法的另一个实现和推理在here找到。

【问题讨论】:

  • 你不能用std::string 吗?
  • 不要让你的实现适应任何内存泄漏问题,就像你写的那样,你有。先解决内存泄漏问题,再充分利用动态内存分配。
  • 有什么特殊要求为什么不能在堆上分配?您提供的解决方案是 IMO 唯一能够在堆栈上分配它的解决方案。那时你将不得不忍受尺寸上的缺点。
  • 旁注:不要使用__buf 之类的名称,以两个下划线开头。他们是reserved
  • @DesmondHume 当然我修复了我发现的内存问题,但为了确保它们不会重复,我想添加一些保护机制。我们没有使用动态分配,因为在实时应用程序中分配非常耗时。

标签: c++ string templates


【解决方案1】:

这似乎是使用模板时最合乎逻辑和最精确的方式。按照Torsten Robitzki 的建议,尝试从您的可执行文件中删除调试符号。

根据您的编译器,尤其是用于实时嵌入式系统的旧编译器,模板可能会迅速膨胀二进制文件大小。如果是这种情况,有几个选项可以避免使用模板:

  • 实施分配策略。如果BufferString 写入正确,那么它拥有的内存(m_buf)可以在堆栈或堆上分配而不会引入泄漏。如果碎片和时间而不是内存泄漏是避免堆的主要原因,那么需要考虑许多专门用于缓解实时系统上的这些问题的分配模式,例如池或静态分配模式。李>
  • 如果必须避免堆,并且模板会导致过多的膨胀,那么另一种选择是手动分别声明缓冲区和MyString。尽管我会尽量避免它,但宏可能会在可用性和可读性之间提供适当的折衷。例如,以下宏可用于声明自动变量:

    #define BUFFER_STRING(name, size)  \
      char name##buffer[size];         \
      MyString name(name##buffer, size)
    

【讨论】:

  • 谢谢。看来我必须在使用宏(内存高效)和使用模板(方便)之间做出决定,因为没有提出其他解决方案。我还将测试模板如何影响剥离的二进制文件。
【解决方案2】:

从您的可执行文件中去除调试符号。每个实例 1k 可能不是 c'tor 的代码,而是调试符号。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-10
    • 2016-10-22
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多