分配大小无效?C++

Invalid allocation size? c++

本文关键字:C++ 无效 分配      更新时间:2023-10-16

我得到了三个文件:

文本.h

#include <string>
namespace w3
{
    class Text
    {
        std::string file_name;
        std::string* handler;
        int records;
    public:
        Text();
        Text(char*);
        size_t size() const;
        Text(const Text& );
        Text& operator=(const Text&);
        Text(Text&&);
        Text&& operator=(Text &&);
        ~Text();
    };
}

文本.cpp

#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
#include "Text.h"
namespace w3
{
    Text::Text()
    {
        file_name = "";
        handler = nullptr;
        records = 0;
    }
    Text::Text(char* file)
    {
        file_name = file;
        if (file[0]='')
        {
            file_name=" ";
            std::cout << "can not find file name !!" <<std::endl;
        }
        else
        {
            std::fstream f(file_name);
            std::string line;
            if (f.is_open()) //ERROR
            {
                while (std::getline(f,line,'n'))
                {
                    records++;
                }
            }
            else
            {
                std::cout << "file not open !!" <<std::endl;
            }
            std::string* handle = new std::string[size()];
            f.clear();
            f.seekg(0,std::ios::beg);
            int counter = 0;
            while (std::getline(f,line,'n'))
            {
                if (counter != records)
                {
                    handle[counter]=line;
                    counter++;
                }
            }
        }
    }
    size_t Text::size() const
    {
        return (size_t)records;
    }
    Text::Text(const Text& src)
    {
        std::string file_name = src.file_name;
        int no_of_rec = src.records;
        if (src.handler != nullptr)
        {
            handler = new std::string[src.size()];
            handler = src.handler;
        }
        else
        {
            handler = nullptr;
        }
    }
    Text& Text::operator=(const Text& src)
    {
        if (this != &src)
        {
            int no_of_rec = src.records;
            std::string file_name = src.file_name;
            if (src.handler != nullptr)
            {
                handler = new std::string[src.size()];
                handler=src.handler;
            }
            else
            {
                handler = nullptr;
            }
        }
        return *this;
    }
    Text::Text(Text&& src)
    {
        file_name=src.file_name;
        handler = src.handler;
        records = src.records;
        src.file_name = " ";
        src.handler = nullptr;
        src.records = 0;
    }
    Text&& Text::operator=(Text&& src)
    {
        if (&src != this)
        {
            file_name = src.file_name;
            handler = src.handler;
            records = src.records;
            src.file_name = " ";
            src.handler = nullptr;
            src.records = 0;
        }
        return std::move(*this);
    }
    Text::~Text()
    {
        //delete [] handler;
    }
}

W3.cpp

 #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[]) {
     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";
 }

我在函数 Text::Text(char* 文件( 的 if (f.is_open((( 行出现错误。

现在,我进行了调试并得出结论,该错误会导致分配大小无效。

当我进一步检查错误时,我注意到记录值将有一个荒谬的负数,例如 -858993460!

我需要有关如何解决此问题的指示。

正在打开的文本文件是一个非常大的文件......

谢谢。

让我们首先说,您可以消除此代码的主要部分,并且如果您使用 std::vector<std::string> 作为handler成员而不是 std::string*,则发生错误的可能性很小。

话虽如此,一个明显的错误是你有一个错误的复制构造函数。 您不会从传递给您的Text对象复制所有信息。 您遗漏了file_namerecords成员,使它们未初始化。

此外,handler成员变量设置不正确 - 您分配内存,然后再次this->handler设置为指向传入对象的handler成员的指针。 这是完全不正确的。

复制构造函数应分配一个新数组,然后将字符串从传入的对象复制到新对象的handler成员。

复制构造函数应如下所示:

Text::Text(const Text& src) : file_name(src.file_name),
                              records(src.records),
                              handler(nullptr)
{
    if ( src.handler )
    {
        handler = new std::string[src.records];
        for (size_t i = 0; i < src.records; ++i )
            handler[i] = src.handler[i];
    }
}

完成此操作后,从析构函数中删除注释 - delete [] handler;应该取消注释。

完成所有这些操作后,赋值运算符很简单:

#include <algorithm>
//...
Text& operator=(const Text& src)
{
   Text tmp(src);
   std::swap(tmp.handler, handler);
   std::swap(tmp.records, records);
   std::swap(tmp.file_name, file_name);
   return *this;
}

这使用复制/交换习惯用法。 基本上,这样做所做的就是从传入的对象创建一个临时对象,并将其内部结构与this的内部结构交换。 然后临时对象随旧数据一起死亡。