如何将非null终止的字符串复制到动态内存

时间:2016-11-05 22:04:57

标签: c++ dynamic-memory-allocation memcpy delete-operator hang

首先,这不是duplicate。我的问题是如何使用动态内存。这是不同的原因是因为delete[]悬而未决。

所以,这就是我所拥有的:

class PacketStrRet {
    public:
    PacketStrRet(char p_data[], int p_len) : len(p_len) {
        data = new char[p_len];
        memcpy(data, p_data, p_len * sizeof(char));
    }

    ~PacketStrRet() { 
        delete[] data; 
        data = nullptr;
    }

    char* data;
    int len;
};

是的,我知道我的代码没有使用最佳做法。我稍后会把它清理干净。

我遇到的问题是在DTOR中。那个删除永远都是悬而未决传递给CTOR的数据是不是动态内存,因此我需要将其设置为动态,因此事情不会超出范围。 p_len保存正确的数据量,因此没有任何问题。

从我所读到的内容来看,memcpy似乎是最可能的罪魁祸首。那么如何将一个非空终止的字符串复制到动态内存中,然后仍然可以在以后删除它?

感谢。

2 个答案:

答案 0 :(得分:1)

问题不在于删除,只有之前的所有事情,如果没有出现任何问题,那就没问题。

class PacketStrRet {
    // Use RAII
    std::unique_ptr<char> data; // I own this data and will destroy it.
    // now the parent class is also only movable, use shared_ptr if you can't live with that.
    int len;

    public:
    PacketStrRet(
        // <RED ALERT>
        char p_data[], int p_len // user can lie to us.
        // </RED ALERT>
        ) try : // function try block, se 1)
          len(p_len), data(new char[p_len]) {
        memcpy(data, p_data.get(), p_len * sizeof(char));
    } catch(const std::exception& e) {
      std::cerr << "arg=" << arg << " failed: " << e.what() << '\n';
    }

    ~PacketStrRet() { 
        // unique_ptr takes care of memory management and garbage collection.
    }   
    // access functions
};

现在可能会出现错误,可能会导致代码崩溃。

您可以复制该对象,实际上是两个拥有相同数据的原始指针。这会在删除时爆炸,你可以使用memory-sanitizer / valgrind来确认这种情况。使用智能指针可以省去麻烦,如果您尝试复制,唯一指针导致编译器错误,除非您记住整个结构忽略复制/赋值构造函数。

你可以给构造函数赋予错误的len,数据和len的来源是什么? Valgrind /记忆消毒剂可以拯救你。

内存损坏可能发生在一个完全不同的地方。 Valgrind /记忆消毒剂可以拯救你。

如果valgrind mem-san太多,你可以尝试检查双删除,如果你在c'tor和d'tor中制作一个计数器,如果它变为负数你就会有错误。< / p>

在这个类中,你至少缺少一个复制构造函数。检查规则3,5,7和0(零)以找出您需要的数量。

1)http://en.cppreference.com/w/cpp/language/function-try-block

答案 1 :(得分:-1)

尝试使用std :: copy()。它会是这样的: std::copy(p_data, p_data + p_len, data).