我试图编写将Student对象的名称设置为新名称的代码,但是我在创建字符数组时遇到了内存泄漏错误。我假设它与数组末尾的/ 0有关,并且没有正确终止,但我不知道如何正确解决这个问题。谢谢您的帮助。
#include "student.h"
#include <string>
#include <cstring>
#include <iostream>
using namespace std;
Student::Student(const char * const name, int perm) {
this->setName(name);
this->setPerm(perm);
}
int Student::getPerm() const {
return this->perm;
}
const char * const Student::getName() const {
return this->name;
}
void Student::setPerm(const int perm) {
this->perm = perm;
}
void Student::setName(const char * const newName) {
this->name = new char[strlen(newName)+1];
// this->name[srtlen(newName)+1] = '/0'; <---- My suggested fix, but doesn't work
strcpy(this->name,newName);
}
Student::Student(const Student &orig) {
this->setName(orig.getName());
this->setPerm(orig.getPerm());
}
Student::~Student() {
delete this->name;
this->perm = 0;
}
这是valgrind错误:
==13814== Invalid read of size 1
==13814== at 0x4C2BA12: strlen (vg_replace_strmem.c:454)
==13814== by 0x4F56FD6: UnknownInlinedFun (char_traits.h:267)
==13814== by 0x4F56FD6: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (basic_string.h:456)
==13814== by 0x401ED8: Student::toString[abi:cxx11]() const (student.cpp:64)
==13814== by 0x401A46: main (testStudent00.cpp:14)
==13814== Address 0x5302e8 is not stack'd, malloc'd or (recently) free'd
==13814==
答案 0 :(得分:2)
您认为需要添加0终止符是错误的,strcpy()会为您执行此操作。你这样做的尝试将0终结符添加到你分配的空间之后一个字节(记住,数组索引从零开始),语法也是错误的,你需要这样做:
this->name[strlen(newName)] = '\0';
但是,要修复内存泄漏,您需要删除上一个字符串,例如
void Student::setName(const char * const newName)
{
delete [] this->name;
this->name = new char[strlen(newName)+1];
strcpy(this->name,newName);
}
Student::Student(const Student &orig) :
name(0) {
this->setName(orig.getName());
this->setPerm(orig.getPerm());
}
Student::~Student() {
delete [] this->name;
this->perm = 0;
}
现在,为了使其工作,您还需要修复构造函数和复制构造函数以初始化name成员,因此它不是第一次调用setName()函数的未初始化指针,并且您需要添加也是一个赋值运算符,因此您可以正确处理赋值。
Student::Student(const char * const name, int perm) :
name(0)
{
this->setName(name);
this->setPerm(perm);
}
Student &operator=(const Student &orig) {
this->setName(orig.getName());
this->setPerm(orig.getPerm());
}
另外,考虑使用std::string而不是当前处理字符串的低级方式,这样你甚至不需要为这个类实现复制构造函数,赋值运算符和析构函数,也不需要正确管理存储器中。