【问题标题】:memcpy for class-level array in copy constructor leads to segfault复制构造函数中类级数组的 memcpy 导致段错误
【发布时间】:2011-02-26 00:18:21
【问题描述】:

有一个模板类用于 4 字母字母表中的序列(=> 每个字母 2 位):

template <size_t _size>
class Seq {
private:
    const static size_t _byteslen = (_size / 4) + (_size % 4 != 0);
    char _bytes[_byteslen];
public:
    Seq() {};
    Seq(const char* s);
    Seq(const Seq<_size> &seq);
    ...
    std::string str() const;
    ...
}

如果复制构造函数被实现为愚蠢的从到字符串,那么一切正常。

Seq(const Seq<_size> &seq) {
    Seq(seq.str().c_str());
}

否则,如果复制构造函数像这样使用 memcpy:

Seq(const Seq<_size> &seq) {
    memcpy(_bytes, seq._bytes, _byteslen);
}

程序在几秒钟后出现段错误(使用完全不同的 std::string 执行 += 或 [] 操作)。这样的 memcpy 可能有什么问题?谢谢。

附: memmove 没有帮助。

【问题讨论】:

  • 您甚至不需要用户声明/定义的复制 ctor。除此之外,我没有看到任何错误。您可能在其他地方有未定义的行为。
  • 强烈建议使用std::vector 或其新的固定大小等效std::array 而不是手动复制内存。
  • 强烈推荐使用编译器生成的拷贝ctor。
  • 编译器生成的复制 ctor 执行相同的段错误。
  • 您需要发布发生段错误的代码行。除了使用下划线前缀(下划线开头的标识符是为编译器保留的)之外,您发布的代码没有任何问题。

标签: c++ g++ memory-management memcpy


【解决方案1】:

“如果复制构造函数被实现为愚蠢的从到字符串,那么一切正常。”

Seq(const Seq<_size> &seq) {
    Seq(seq.str().c_str());
}

真的吗?因为该构造函数根本没有初始化_bytes[]。 (相反,它会创建一个不同的临时 Seq 对象,该对象未使用并立即销毁。)

【讨论】:

  • 谢谢。好吧,关键是它不会使整个程序崩溃,而 memcpy 会。
  • @Nikolay:UB的症状不可靠。不要仅仅因为没有memcpy 行就不会崩溃,就认为程序的其余部分没问题。 UB 只会在某些偶然(且很大程度上不可预测)的情况下导致崩溃。
【解决方案2】:

只是一个猜测:您的 str() 函数将 _bytes 作为字符串返回,试图从非 nul 终止的缓冲区构建它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多