返回 0 之前的主要崩溃



我正在用C++编写一个程序,遇到了最奇怪的错误。我的程序在 main 返回 0 之前崩溃。

我不明白程序如何在完成后崩溃,但在返回零之前崩溃。

这怎么可能?

主要有以下几点:

#include <iostream>
#include <iomanip>
#include <utility>
#include <ctime>
#include "Text.h"
#define TIME(start, end) double((end) - (start)) / CLOCKS_PER_SEC

int main(int argc, char* argv[]) {
    argv[1] = "gutenberg_shakespeare.txt";
    argc = 2;
    if (argc == 1) {
        std::cerr << argv[0] << ": missing file operandn";
        return 1;
    }
    else if (argc != 2) {
        std::cerr << argv[0] << ": too many argumentsn";
        return 2;
    }
    std::clock_t cs, ce;
    std::cout << std::fixed << std::setprecision(3);
    cs = std::clock();
    w3::Text a;
    ce = std::clock();
    std::cout << "Constructor      " << TIME(cs, ce) << " seconds";
    std::cout << " - a.size = " << a.size() << std::endl;
    cs = std::clock();
    w3::Text b(argv[1]);
    ce = std::clock();
    std::cout << "Constructor      " << TIME(cs, ce) << " seconds";
    std::cout << " - b.size = " << b.size() << std::endl;
    cs = std::clock();
    a = b;
    ce = std::clock();
    std::cout << "Copy Assignment  " << TIME(cs, ce) << " seconds";
    std::cout << " - a.size = " << a.size() << std::endl;
    cs = std::clock();
    a = std::move(b);
    ce = std::clock();
    std::cout << "Move Assignment  " << TIME(cs, ce) << " seconds";
    std::cout << " - a.size = " << a.size() << std::endl;
    cs = std::clock();
    w3::Text c = a;
    ce = std::clock();
    std::cout << "Copy Constructor " << TIME(cs, ce) << " seconds";
    std::cout << " - c.size = " << c.size() << std::endl;
    cs = std::clock();
    w3::Text d = std::move(a);
    ce = std::clock();
    std::cout << "Move Constructor " << TIME(cs, ce) << " seconds";
    std::cout << " - d.size = " << d.size() << std::endl;
    cs = std::clock();
    ce = std::clock();
    std::cout << "Destructor       " << TIME(cs, ce) << " secondsn";
    std::cout << "DONE";
    return 0;
}

文本 cpp 文件:

#include "Text.h"
#include <fstream>
#include <iostream>
using namespace w3;
Text::Text() {
}
//MOVE Copy constructor
Text::Text(Text&& movefrom){
    std::cout << "MOE COPY CONSTRUCTOR" << std::endl;
    filename = movefrom.filename;
    entries  = movefrom.entries;
    data     = movefrom.data;
    movefrom.entries = 0;
    movefrom.data    = nullptr;
}
//move assig operator
Text&& Text::operator=(Text&& movefrom) {
    std::cout << "move assig operator" << std::endl;
    if (&movefrom != this) {
        filename = movefrom.filename;
        entries  = movefrom.entries;
        if (data != nullptr) {
            delete[] data;
            entries = 0;
        }
        movefrom.data = nullptr;
    }
    movefrom.entries = 0;
    return std::move(*this);
}
//constructor
Text::Text(const std::string& mystring) {
    std::cout << "Constructor" << std::endl;
    int count = 0;
    filename = mystring;
    std::string buffer;
    std::ifstream myfile(filename);
    if (!myfile.is_open()) {
        filename.clear();
    }
    if(myfile.is_open()) {
        while (getline(myfile, buffer)) { //Will fail at end of file
            //std::cout << buffer << std::endl;
            count++;
        }
        std::cout << "File is read";
        data = new std::string[count];
        myfile.clear();//.................reset file state
        myfile.seekg(0, myfile.beg);//....reset file position
        int x = 0;
        for (int i = 0; i < count; i++) {
            getline(myfile, data[i]);
        }
        std::cout << std::endl << "File is copied" << std::endl;
        entries = count;
        myfile.close();
    }   
}
//default constructor
Text::~Text() {
    if (data != nullptr) {
        delete[] data;
        entries = 0;
    }
    data = nullptr;
}
//copy constructor
Text::Text(const Text& copyfrom) {
    data  = nullptr;  //The object is empty
    *this = copyfrom;
}
const Text& Text::operator=(const Text& copyfrom) {
    std::cout << "copy assign operator" << std::endl;
    if (this != &copyfrom) {
        if (data != nullptr) {
            delete[] data;
            entries = 0;
        }
        filename = copyfrom.filename;
        entries = copyfrom.entries;
        if (copyfrom.data != nullptr) {  //If the object is not empty
            data = new std::string[entries];
            for (int i = 0; i < entries; i++) {
                data[i] = copyfrom.data[i];
            }
        }
        std::cout << "Data is assigned" << std::endl;
    }
    return *this;
}

size_t Text::size() const {
    return entries;
}
void Text::print() {
    for (int i = 0; i < entries; i++) {
        std::cout << data[i] << std::endl;
    }
}

编辑>>>头文件

#ifndef TEXT_H
#define TEXT_H

#define FILE_LENGTH 10
#include <string>
#include <iostream>

namespace w3 {
    class Text {
    private:
        std::string filename;
        std::string * data = nullptr;
        size_t entries;
    public:
        Text(Text&& movefrom);
        Text&& operator=(Text&& movefrom);
        Text();
        Text(const std::string& mystring);
        Text(const Text& copyfrom);
        ~Text();
        const Text& operator=(const Text& copyfrom);
        size_t size() const;
        void print();
    };
}
#endif

我不得不说,失败不是我所期望的。为此向OP致敬。我预计会进行双重删除,因为两个对象指向同一个池。因此,这不是普通的三条规则违规;有点不同。

快速浏览说复制逻辑很好(如果可以的话,请考虑对数据使用 std::vector"如果你这样做,你可以扔掉大约 1/4 的代码)和最大的死亡点是一个不完整的默认构造函数。

w3::Text a;

将调用基本默认构造函数

Text::Text() {
} 

这不会将data初始化为 nullptr .这会导致const Text& Text::operator=(const Text& copyfrom)问题:

if (data != nullptr)
{
    delete[] data;
    entries = 0;
}

a=b; a.data从未设置时,不太可能nullptr,并且会尝试释放不属于它的存储空间。如果程序设法跛行通过这个,它可以,它的状态现在无效,Crom只知道它什么时候会失败。

Text::Text(): entries(0), data(nullptr)
{
}

解决了这个问题。

也。。。

复制构造函数泄漏

Text::Text(const Text& copyfrom)
{
    data = nullptr; //The object is empty
    *this = copyfrom;
}

你怎么知道数据是空的?没有测试,所以噗!如果那里有什么,现在无法到达。但正如 Paul McKenzie 上面指出的那样,根据 Copy 构造函数编写赋值运算符几乎总是更好的。

移动分配运算符有点不稳定。

Text&& Text::operator=(Text&& movefrom)

应该是

Text& Text::operator=(Text&& movefrom)

这意味着您不必清除this return std::move(*this); .只是return *this;

在析构函数中没有意义

data = nullptr;

该对象在该行之后立即销毁,因此清空data是浪费精力。

相关内容

  • 没有找到相关文章

最新更新