默认构造函数的分段错误

Posted

技术标签:

【中文标题】默认构造函数的分段错误【英文标题】:Segmentation fault on default constructor 【发布时间】:2018-09-13 04:59:45 【问题描述】:

当我运行我的代码时,调用默认构造函数时会出现分段错误,但不是每次调用它。当我在重载 + 运算符后尝试动态分配新内存时,它会出错。我知道 seg 错误是由于指针的滥用而发生的,但我称之为 def。代码中的构造函数,它可以工作。

here 是一个带有 main 和 header 的 git repo(如果需要):

#include <iostream>
#include "proj1-5-MyString.h"
#include <cmath>

using namespace std;

    MyString::MyString() 
        capacity = 10;
        size = 0;
        data = new char[capacity];
        data[size] = '\0';
    

//Constructor

MyString::MyString(const char *input) 
    this->capacity = 10;
    this->size = 0;
    this->data = new char[this->capacity];
    for (int count = 0; input[count] != '\0'; count++) 
        if (count >= this->capacity) 
            this->capacity *= 2;
            char *temp = new char[this->capacity];
            for (int i = 0; i < this->size; i++) 
                temp[i] = this->data[i];
            
            delete[] this->data;
            this->data = temp;
            delete[] temp;
        
        this->data[count] = input[count];
        this->size = count + 1;
    
while ((double) this->size < 0.25 * ((double) (this->capacity))) 
    this->capacity = (int)floor(this->capacity / 2);


this->data[this->size + 1] = '\0';


//Constructor with an initialization character string

MyString::~MyString() 
    delete[] this->data;
    data = NULL;



//Destructor
MyString::MyString(const MyString &that) 
    this->data = new char[this->capacity];
    this->capacity = that.capacity;
    this->size = that.size;

    for(int i = 0; i < size; i++)
        this->data[i] = that.data[i];
    

    while(this->size < 0.25 * (double)(this->capacity))
        this->capacity = (int)((double)that.capacity / 2.0);
    



//Copy constructor
MyString &MyString::operator=(const MyString &input) 
    if (this->data != input.data) 
        delete[] this->data;
        this->capacity = input.capacity;
        this->size = input.size;

        int charCount = 0;
        for ( charCount; charCount < input.size; charCount++) 
            if (charCount >= this->capacity) 
                this->capacity *= 2;
                char *temp = new char[this->capacity];

                for (int j = 0; j < charCount; j++) 
                    temp[j] = this->data[j];
                
                delete[] this->data;
                this->data = temp;
                delete[] temp;
            
            this->data[charCount] = input.data[charCount];
            this->size = charCount + 1;
        
    

    return *this;


//Overloaded assignment operator, make a copy of MyString object
bool MyString::operator==(const MyString &otherString) const 
    int i = 0;
    bool same = true;

    if (this->size == otherString.size) 
        while (i < otherString.size) 
            if (this->data[i] == otherString.data[i]) 
                same = i <= size;
             else 
                same = false;
            
            i++;
        
     else 
        same = false;
    
    return same;


//overloaded equivalence relational operator
char &MyString::operator[](int val) 
    return this->data[val];


//overloaded [ ] should return a char by reference
void MyString::operator+=(const MyString &otherStr) 
    *this = *this + otherStr;


//overloaded += operator, use to concatenate two MyStrings
MyString MyString::operator+(const MyString &otherStr) const 

//SEGFAULT HERE

MyString doubleString;
    cout << doubleString.capacity << endl;
    while (doubleString.capacity < (this->size + otherStr.size)) 
        doubleString.capacity *= 2;
    

    for (int i = 0; i < max(this->size, otherStr.size); i++) 
        doubleString.data[i] = this->data[i];
        doubleString.data[i + this->size] = otherStr.data[i];

    

    doubleString.size = this->size + otherStr.size;
    return doubleString;


//Create a new MyString object that is the concatenation of two MyString
//objects
void MyString::getline(istream &in, char delimit) 
    delimit = '\n';
    int size = 10;
    char buffer[size];
    int charNum = 0;
    while (in.get(buffer[charNum++])) 
        if (buffer[charNum - 1] == delimit) 
            break;
        
        if (charNum >= size) 
            char *temp = new char[size * 2];
            for (int j = 0; j < size; j++) 
                temp[j] = data[j];
            
            delete[] data;
            data = temp;
            delete[] temp;
        
    


//reads an entire line from a istream. Lines are terminated with delimit
//which is newline ‘\n’ by default
int MyString::length() const 
    return this->size;


//return the length of the string
ostream &operator<<(ostream &out, MyString &stringWord) 
    for (int i = 0; i < stringWord.size; i++) 
        out << stringWord.data[i];
    
    return out;

//overloaded insertion operator

【问题讨论】:

你能发布一个重现这个问题的小函数吗?至少有时?另外,当你得到段错误时,this 的值是多少? 【参考方案1】:

例如,如果您有以下代码:

MyString s0 = "ABC";
MyString s1 = "DEF";

auto s2 = s0 + s1;

第一个问题出在MyString的构造函数中。您的字符串没有被\0 终止。

这可以很容易地解决:

MyString::MyString(const char *input)

    this->capacity = 10;
    this->size = 0;
    //this->data = new char[this->capacity]; //<- Old
    this->data = new char[this->capacity](); //<- New

有多个地方没有初始化分配的 char 数组。请检查您的代码并这样做。通过char() 构造函数或其他各种方式(std::fillmemset、...)。


请记住在发布问题之前调试您自己的代码。您可以很容易地在调试器中发现这一点。

【讨论】:

以上是关于默认构造函数的分段错误的主要内容,如果未能解决你的问题,请参考以下文章

构造函数中的分段错误不明确

由于构造函数,即将出现分段错误

带有 QWidget 的分段错误构造函数。 Qt/C++

构造函数内部变量的定义会导致分段错误

具有显式构造函数的类是不是需要在 emplace 中使用分段构造?

为啥这个非常简单的构造函数会导致段错误?