【问题标题】:Is there a memory leak?有内存泄漏吗?
【发布时间】:2016-03-20 14:44:38
【问题描述】:

我尝试使用 Microsoft Visual Studio 2015 在 C++ 中编写自己的 String 类。我是这样编写的;

#include<string.h>
class myString {
    private:
        char* content;
    public:
        int size;
        myString();
        myString(char*);
        ~myString();
        bool operator==     (const myString &) const;
        bool operator!=     (const myString &) const;
        myString operator=  (const myString &);
        myString operator+  (const myString &) const;
        myString operator+= (const myString &);
        friend std::ostream& operator<< (std::ostream &os, const myString &);
        char operator[] (int &) const;
};

std::ostream& operator<<(std::ostream &os, const myString &string) {
    os << string.content;
    return os;
}

myString::myString() {
    size = 0;
    content = "\0";
}

myString::myString(char* newContent) {
    size = strlen(newContent);
    content = new char[size+1];
    strcpy(content, newContent);
}

myString::~myString() {
    delete[] content;
}

myString myString::operator= (const myString &string) {
    if (size != string.size) {
        delete[] content;
        size = string.size;
        content = new char[size+1];
    }
    strcpy(content, string.content);
    return *this;
}

bool myString::operator== (const myString &string) const {
    if (size != string.size)
        return false;
    if (strcmp(content, string.content))
        return false;
    return true;
}

bool myString::operator!= (const myString &string) const {
    if (*this == string)
        return false;
    return true;
}

myString myString::operator+ (const myString &string) const {
    int newSize = size + string.size;
    char* newContent = new char[newSize];
    strcpy(newContent, content);
    strcat(newContent, string.content);
    return myString(newContent);
}

myString myString::operator+= (const myString &string) {
    *this = *this + string;
    return *this;
}

char myString::operator[] (int &index) const {
    return content[index];
}

当我尝试这样做时效果很好;

#include<iostream>
#include "MyString.h"
using namespace std;

int main() {
    myString s("my new");
    cout << s+" string" << endl;    
}

但我不确定operator+ 行中的char* newContent = new char[newSize]; 函数中是否有任何内存泄漏我正在从内存中分配新空间,我在返回语句return myString(newContent); 中需要它。

所以我不能在这一行之前释放它,我不能在 return 语句之后释放它。我是对的,有内存泄漏吗?如果是这样,我该如何解决这个问题?

编辑 1: 在 Dhaliwal 王子的帮助下,我将 operator+ 函数更改如下;

myString myString::operator+ (const myString &string) const {
    myString temp;
    int newSize = size + string.size;
    char* newContent = new char[newSize + 1];
    temp.size = newSize;
    strcpy(newContent, content);
    strcat(newContent, string.content);
    temp.content = newContent;
    return temp;
}

但是由于我在本地创建了temp,它在返回之前调用了它的析构函数并给出了错误。我想我也应该为 temp 分配内存。我将功能更改如下;

myString myString::operator+ (const myString &string) const {
    myString* temp= new myString;
    int newSize = size + string.size;
    char* newContent = new char[newSize+1];
    temp->size = newSize;
    strcpy(newContent, content);
    strcat(newContent, string.content);
    temp->content = newContent;
    return *temp;
}

它现在工作正常,但我相信由于temp 变量仍然存在内存泄漏。如果存在内存泄漏,如何解决?

编辑 2: 我只是通过创建一个复制构造函数来修复它

【问题讨论】:

  • 分析您的代码,然后您就知道是否存在内存泄漏。如果是这样,您可以尝试查找位置。
  • 当 STL 有字符串类时,为什么要这样做?
  • 其实这是我的作业,他们禁止我们使用它们。我猜是为了学习目的。
  • 是的,正如您所描述的,存在内存泄漏。
  • 哦,我明白了,你还没有创建复制构造函数myString(const myString&amp;)。实际上发生了什么,默认复制构造函数将进行成员复制,这意味着复制和原始指针 content 都指向同一个内存。当temp 的析构函数被调用时,该内存被删除。

标签: c++ string class memory memory-leaks


【解决方案1】:

您的代码中实际上存在内存泄漏。当您在s + " string" 中使用+ 运算符时。在您的operator+() 定义中,即

myString myString::operator+ (const myString &string) const {
    int newSize = size + string.size;
    char* newContent = new char[newSize];
    strcpy(newContent, content);
    strcat(newContent, string.content);
    return myString(newContent);
}

您在char* newContent = new char[newSize]; 此处分配新字符串,将旧部分和新部分复制到新字符串中。再次在构造函数return myString(newContent); 中分配新字符串。但是你在哪里删除你的旧字符串?它不在您的代码中。所以你必须删除字符串newContent。 你可以这样做

myString myString::operator+ (const myString &string) const {
    myString temp;
    int newSize = size + string.size;
    char* newContent = new char[newSize + 1];
    temp.size = newSize;
    strcpy(newContent, content);
    strcat(newContent, string.content);
    temp.content = newContent;
    return temp;
}

更新 您必须创建一个复制构造函数。

myString(const myString &rhs) :
size(rhs.size) {
    content = new char[size + 1];
    strcpy(content, rhs.content);
}

【讨论】:

  • 感谢您的回答!顺便说一句,我们在为 newContent 分配内存时不应该写 newSize+1,因为 '\0' 字符?
  • 此外,我们在本地创建了临时字符串。所以当这个 operator+ 函数完成时,它会调用 temp 的析构函数。我该如何处理?
  • temp的析构函数被调用之前,它会被复制,因为你返回了局部变量的副本,这很好。
  • 我用的是Visual Studio的调试器。在返回行中,在它返回 temp 之前,它经过 temp 的析构函数,清除内容并返回一个没有内容的字符串,当我尝试打印其内容时它会出错。
  • 我们应该为\0 使用newSize + 1。我对代码进行了更改。
猜你喜欢
  • 2019-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多