我有以下代码,并且我不确定为什么当它到达Myclass的析构函数时我检测到堆损坏错误。我相信我正在正确地释放内存?
#include <iostream>
#include <vector>
using namespace std;
class MyClass{
private:
char* mp_str;
public:
MyClass():mp_str(NULL){}
~MyClass(){
delete [] mp_str;
}
void setString(const char* str);
void printString();
};
int main(){
MyClass* a = new MyClass();
std::vector<MyClass> myVector;
myVector.push_back(*a);
a->setString("Hello World");
myVector[0].setString("Goodbye world");
a->printString();
myVector[0].printString();
return 1;
}
void MyClass::setString(const char* const str){
if(!str)
return;
size_t len = strlen(str);
if(!this->mp_str){
this->mp_str = new char[len];
memset(mp_str, 0, len+1);
}
strncpy(mp_str, str, len);
}
void MyClass::printString(){
if(this->mp_str)
cout << mp_str;
else
cout << "No string found";
}
编辑 :(固定代码)
void MyClass::setString(const char* const str){
if(!str)
return;
size_t len = strlen(str);
if(!this->mp_str){
this->mp_str = new char[len+1];
memset(mp_str, 0, len+1);
}
strncpy(mp_str, str, len);
}
在main()中,我还添加了
delete a;
在致电返回1之前;
答案 0 :(得分:8)
您需要分配字符串+1的长度,以便考虑null。你正确的做法。
if(!this->mp_str){
this->mp_str = new char[len+1];
memset(mp_str, 0, len+1);
}
答案 1 :(得分:1)
(在Rafael的回答被接受之后发布,应该是。)
缓冲区溢出肯定是此特定崩溃的根本原因,但是通过在调整遵守Rule of Three的同时简化实现可以避免崩溃。也就是说,既然你实现了一个析构函数(处理mp_str
),那么你也应该实现一个复制构造函数和赋值运算符。
但是,坚持TRoT的另一种方法是避免需要实现任何这些东西。在这种情况下,使用std::string
代替char *
可以解决崩溃并符合TRoT标准:
class MyClass{
private:
std::string mp_str;
public:
void setString(const char* str) { mp_str = str ? str : ""; }
void printString() {
if (mp_str.size()) std::cout << mp_str;
else std::cout << "(mp_str is empty)";
}
};