2017-05-20 12 views
0

학생 개체의 이름을 새 이름으로 설정하는 코드를 작성하려고하지만 문자 배열을 만들 때 메모리 누수 오류가 발생합니다. 배열의 끝에/0과 관련이 있다고 가정하고 제대로 종료하지는 않지만 올바르게 수정하는 방법을 모르겠습니다. 도와 주셔서 감사합니다. valgrind 사용 - "크기 1의 잘못된 읽기"strlen

#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

'const char *'대신'std :: string'을 사용하십시오. – arboreal84

답변

2

당신이 0 터미네이터를 추가 할 필요가 귀하의 가정이 잘못, strcpy를() 당신을 위해 그렇게 할 것입니다. 그렇게 귀하의 시도가 당신이 (배열 인덱스는 0에서 시작, 기억)에 할당 된 공간을지나 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; 
} 

처럼, 당신은 이전의 문자열을 삭제해야 누출 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를 사용하는 것이 좋습니다 당신도이 클래스의 복사 생성자, 할당 연산자 및 소멸자를 구현도 제대로 관리를 처리 할 필요가 없습니다 그 방법 기억.

+0

당신의 제안에 감사드립니다! 그러나, 나는 지금이 -> 이름을 삭제하려고 시도하고 그것은 런타임 동안 더 큰 메모리 오류 메시지를 만들었습니다. –

+0

생성자도 업데이트해야합니다. 새 코드를 확인하십시오. – nos

+0

나는 여전히 같은 오류가있는 것 같습니다. std :: string으로 변경하고 포인터 초기화를 추가했습니다. 또한 if (this-> name! = NULL)을 삭제 한 다음 this-> name을 삭제하는 if 문을 추가하려고 시도했지만 도움이되지 않았습니다. 혹시 다른 아이디어가 있으십니까? –