【问题标题】:allocating and deallocating dynamic memory seg fault in c++在 C++ 中分配和释放动态内存段错误
【发布时间】:2020-04-01 19:14:16
【问题描述】:

这个项目的主要目标是实现我在动态内存分配和释放方面的知识。到目前为止,我的程序编译并运行,但我遇到的唯一问题是编译器在程序结束时声明分段错误(核心转储)。我不知道究竟是什么原因造成的。提供了 int main,所以唯一的必须与我的成员定义有关,我认为这与我的运算符重载(可能是运算符 +)有关,但无法弄清楚如何修复它。是的,我也在使用命名空间标准。有什么建议么?谢谢!

int main(){

//(1)
std::cout << "Testing Default ctor" << std::endl;
MyString ms_default;

//(2)
std::cout << "Testing Parametrized ctor" << std::endl;
MyString ms_parametrized("MyString parametrized constructor!");

//(3)
std::cout << "Testing Copy ctor" << std::endl;
MyString ms_copy(ms_parametrized);

//(4)
std::cout << "Testing dtor" << std::endl;
{
    MyString ms_destroy("MyString to be destroyed...");
}

//(5),(6)
MyString ms_size_length("Size and length test");
std::cout << "Testing size()" << std::endl;
cout << ms_size_length.size() << endl;
std::cout << "Testing length()" << std::endl;
cout <<ms_size_length.length() << endl;

//(7)
std::cout << "Testing c_str()" << std::endl;
MyString ms_toCstring("C-String equivalent successfully obtained!");
cout << ms_toCstring.c_str() << endl;

//(8)
std::cout << "Testing operator==()" << std::endl;
MyString ms_same1("The same"), ms_same2("The same");
if (ms_same1==ms_same2)
    cout << "Same success" << endl;

MyString ms_different("The same (NOT)");
if (!(ms_same1==ms_different))
    cout << "Different success" << endl;

//(9)
std::cout << "Testing operator=()" << std::endl;
MyString ms_assign("Before assignment");
ms_assign = MyString("After performing assignment");

//(10)
std::cout << "Testing operator+" << std::endl;
MyString ms_append1("The first part");
MyString ms_append2(" and the second");
MyString ms_concat = ms_append1+ ms_append2;

//(11)
std::cout << "Testing operator[]()" << std::endl;
MyString ms_access("Access successful (NOT)");
ms_access[17] = 0;

//(12)
std::cout << "Testing operator<<()" << std::endl;
cout << ms_access << endl;

return 0;

}

以下是我的类成员的实现或定义

void MyString::buffer_deallocate(){
if(m_buffer != NULL){
    delete [] m_buffer;
}
}

void MyString::buffer_allocate(size_t size){
if(m_buffer != NULL){
    buffer_deallocate();
}

m_size = size;
m_buffer = new char[m_size];
}

MyString::MyString(){
m_size = 0;
m_buffer = NULL;
}

MyString::MyString(const char * str){
m_buffer = NULL;
m_size = strlen(str);
buffer_allocate(m_size);
strcpy(m_buffer,str);
}

MyString::MyString(const MyString & other){
m_buffer = NULL;
m_size = other.m_size;
buffer_allocate(m_size);
strcpy(m_buffer,other.m_buffer);
}

size_t MyString::size() const {
return m_size;
}

size_t MyString::length() const{
return strlen(m_buffer) - 1;
}

const char * MyString::c_str() const {
char * str = NULL;

    str = new char[m_size];
    for(size_t i = 0; i < m_size; i++){
        str[i] = *(m_buffer+i);
    }

        return str;
        delete [] str;
        str = NULL;
 }

bool MyString::operator==(const MyString & other) const{
if(strcmp(m_buffer,other.m_buffer)==0){
    return true;
}
else if(strcmp(m_buffer,other.m_buffer)!=0){
    return false;
}
}

MyString & MyString::operator=(const MyString & str1){
buffer_deallocate();
m_buffer = new char[str1.m_size];
strcpy(m_buffer, str1.m_buffer);
}

MyString MyString::operator+(const MyString & other_myStr) const {
MyString myStr(strcat(m_buffer, other_myStr.m_buffer));
return myStr;
}

char & MyString::operator[](size_t index){
size_t counter = 0;
while(counter != index){
    counter++;
}
return m_buffer[counter];
}

const char & MyString::operator[](size_t index) const{
size_t counter = 0;
while(counter != index){
    counter++;
}

return m_buffer[counter];
}

std::ostream & operator<<(std::ostream & os, const MyString & myStr){
//if(&os == &std::cout){
    os << myStr.m_buffer << std::endl;
//}
}

MyString::~MyString(){
m_size = 0;
delete [] m_buffer;
}

这是我的班级声明

class MyString{


public:
    MyString();
    MyString(const char * str);
    MyString(const MyString & other_myStr);
    ~MyString();

    size_t size() const;
    size_t length() const;
    const char * c_str() const;

    bool operator==(const MyString & other_myStr) const;
    MyString & operator=(const MyString & other_myStr);
    MyString operator+(const MyString & other_myStr) const;
    char & operator[](size_t index);
    const char & operator[](size_t index) const;

friend std::ostream & operator<<(std::ostream & os, const MyString & myStr);

private:
    void buffer_deallocate();
    void buffer_allocate(size_t size);

    char * m_buffer;
    size_t m_size;

};

【问题讨论】:

  • 这并没有解决问题,但在if(m_buffer != NULL){ delete [] m_buffer; } 中,您不需要测试NULL。运算符 delete 知道空指针。
  • operator[] 可以更简单:只需return m_buffer[index];。而在析构函数中设置m_size = 0; 是没有意义的:对象正在被销毁,所以m_size 将不再存在。
  • 关于operator==,请记住strcmp 可能会查看字符串中的每个字符。运行两次非常浪费,而且完全没有必要。 return strcmp(m_buffer, other.m_buffer) == 0;。或者,由于您事先知道大小,通常可以跳过比较:return m_size == other.m_size &amp;&amp; strcmp(m_buffer, other.m_buffer) == 0;。如果大小不同,将跳过对 strcmp 的调用。
  • 关于赋值运算符,考虑一下这里发生了什么: MyString str("abcd"); str = str;`.

标签: c++ segmentation-fault pass-by-reference operator-keyword friend


【解决方案1】:
m_size = strlen(str);
buffer_allocate(m_size);
strcpy(m_buffer,str);

strlen 告诉您str 指向的字符串中有多少个字符,不包括末尾的 nul 字符。 strcpy 复制 整个 字符串,包括 nul 字符。所以副本会在分配空间的末尾运行。

此外,operator+ 连接字符串而不确保结果有足够的空间。那是行不通的。

【讨论】:

  • MyString d1; d1.size = (my1.size - 1); // 删除第一个空值 d1.string = new char[d1.size]; // 释放一个新数组 int i; for(i = 0; my1.string[i] != '\0'; i++) d1.string[i] = my1.string[i];
  • 然后返回 d1。这对 operator + 来说会更好吗?
  • .size 我的意思是 m_size 和 .string 我的意思是 .m_buffer
  • 对于operator+,新字符串的长度是第一个字符串中的字符数加上第二个字​​符串中的字符数加上一个用于nul终止符的字符。至少分配那么多,然后是strcpystrcat
猜你喜欢
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 2013-11-22
  • 1970-01-01
  • 1970-01-01
  • 2017-06-13
  • 2013-01-27
相关资源
最近更新 更多