使用 valgrind - "Invalid read of size 1" for strlen
Using valgrind - "Invalid read of size 1" for strlen
我正在尝试编写将 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 的假设是错误的,strcpy() 会为您完成。您这样做的尝试在您分配的 space 之后添加了一个字节的 0 终止符(记住,数组索引从零开始),并且语法也是错误的,您需要这样做:
this->name[strlen(newName)] = '[=10=]';
但是,要修复内存泄漏,您需要删除之前的字符串,例如
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;
}
现在,为了让它工作,您还需要修复构造函数和复制构造函数以初始化名称成员,因此它不是第一次调用 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 而不是当前处理字符串的低级别方式,这样您甚至不需要为此 class 实现复制构造函数、赋值运算符和析构函数,也不处理正确管理内存的问题。
我正在尝试编写将 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 的假设是错误的,strcpy() 会为您完成。您这样做的尝试在您分配的 space 之后添加了一个字节的 0 终止符(记住,数组索引从零开始),并且语法也是错误的,您需要这样做:
this->name[strlen(newName)] = '[=10=]';
但是,要修复内存泄漏,您需要删除之前的字符串,例如
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;
}
现在,为了让它工作,您还需要修复构造函数和复制构造函数以初始化名称成员,因此它不是第一次调用 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 而不是当前处理字符串的低级别方式,这样您甚至不需要为此 class 实现复制构造函数、赋值运算符和析构函数,也不处理正确管理内存的问题。