c++ - 内存泄漏错误?

标签 c++ memory-leaks

对于与动态内存和复制构造函数相关的简单赋值,我的教授为我们分配了一个简单的赋值,但在我第二次执行 delete [] 时出现错误。

头文件:

class Stream {
    int len;
    char *hold;
    char* newmem(int);
public:
    Stream ();
    Stream (int);
    Stream(const char *);
    ~Stream ( );
    void operator=(const Stream &);
    Stream(const Stream &);
    friend void show(Stream);
    void operator<<(const char*);
};

它应该相当简单。这是我的代码:

#include <iostream>
#include <new>
#include <cstring>
using namespace std;
#include "stream.h"

char* Stream::newmem(int x) {
    char * tmp;
    try {
        tmp = new char[x];
    }
    catch(std::bad_alloc) {
        tmp = NULL;
    }
    if(tmp)
        cout << "newmem:  " << (void *) tmp << endl;
    return tmp;
}

Stream::Stream ( ) {
    len = 1000;
    hold = newmem(len);
    if (hold)
        strcpy (hold, "");
}

Stream::Stream(int n) {
    len = n;
    hold = newmem(len);
    if (hold)
        strcpy (hold,"");
}

Stream::Stream(const char * dat) {
    len = strlen(dat) +1;
    hold = newmem(len);
    if (hold)
        strcpy(hold,dat);
}

Stream::Stream(const Stream &from) {
    cout << "in the copy constructor, allocating new memory..." << endl;
    cout << "original pointer address is: " << (void *) from.hold << endl;
    cin.get( );

    len=from.len;
    hold=newmem(len +1);
    cout << "new pointer address is: " << (void *) hold << endl;
    cin.get( );

    if(hold)
        strcpy (hold,from.hold);
}

Stream::~Stream ( ) {
    cout << "destruct:  " << (void *) hold << endl;
    cin.get( );
    if (hold)
        delete [] hold;
}

void Stream::operator= (const Stream &from) {
    if(hold)
        delete [ ] hold;
    len = from.len;
    hold=newmem(len +1);
    if (hold)
        strcpy(hold,from.hold);
}

void show (Stream prt) {
    cout << "String is: " << prt.hold << endl << "Length is: " << prt.len << endl;
}

void Stream::operator<< (const char *data) {
    int dlen = strlen(data);
    for (int i=0 ; i<=len && i<=dlen ; i++) {
        hold[i] = data[i];
    }
}

int main( ) {
   char data[ ] = "Growing up it all seems so one-sided;"
                  "Opinions all provided;"
                  "The future pre-decided;"
                  "Detached and subdivided;"
                  "In the mass production zone!"
                  "-Neil Peart- \"Subdivisions\"";

   Stream x1, x2(25), x3;
   x1 << data;
   x2 << data;
   show(x1);
   show(x2);

   x3 = x2;
   show(x3);

   return 0;
}

和我的输出/错误:

in the copy constructor, allocating new memory...
original pointer address is: 0x804c008

new pointer address is: 0x804c808

String is: Growing up it all seems so one-sided;Opinions all provided;The future pre-decided;Detached and subdivided;In the mass production zone!-Neil Peart-Subdivisions"
Length is: 1000
destruct:  0x804c808


in the copy constructor, allocating new memory...
original pointer address is: 0x804c3f8

new pointer address is: 0x804c808

String is: Growing up it all seems so
Length is: 25
destruct:  0x804c808

*** glibc detected *** a.out: free(): invalid pointer: 0x0804c808 ***

最佳答案

operator<< 中的 for 循环有两个差一错误:

for (int i=0 ; i<=len

允许i==len , 但 hold 的唯一有效索引是0..(len-1) .所以,你可以在末尾写一个。

其次,正如 thiton 所指出的,它不会复制 \0终止符,即使有空间。


正确的实现可能是这样的:

void Stream::operator<< (const char *data) {
    int source_len = strlen(data);
    int copy_len = min(source_len, len-1); // allow for terminator

    for (int i=0; i<copy_len; i++) {
        hold[i] = data[i];
    }
    hold[copy_len] = '\0';
}

虽然简单地使用 strncpy 会更好.


请注意,使用半开(或最后一个)范围的习惯用法不仅在直接数组索引中是标准的,而且在 C++ 迭代器中也是标准的。所以,你应该总是期待看到

for (i=0; i<n; ++i) {

for (i = begin; i != end; ++i) {

并且通常应该将像您这样的闭环循环视为值得进一步调查的气味。

关于c++ - 内存泄漏错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15534654/

相关文章:

PHP XML 内存泄漏?

ios - 从 super View 中删除 UIImageView 后内存未释放

winapi - MONITOR 是否需要发布?如果是这样,如何?

c++ - 用宏替换 new 与放置 new 冲突

c - 带 ptrace 的内存调试器

c++ - 每 8 位将 bitset<64> 转换为字符串

c++ - 创建/加入线程时的隐式同步

c++ - 在 C++ 中堆叠/连接 2D vector

c++ - 我的 "if"语句中只有一个给出了准确的值,即使它们都是相同的结构

C++:在不破坏封装的情况下将指针用作私有(private)成员变量?