当我使用push_back()时,C++向量内部的数据发生变化

问题描述 投票:0回答:1

我编写了一个 C++ 函数,它使用“recursive_directory_iterator”来获取父文件夹中所有文件和文件夹的信息。然后我编写了一个名为 DataFolder 的类来存储每个文件的属性,例如文件大小、路径、名称、日期编号等。最后,我使用矢量对象来存储 DataFolder 对象的集合。

对于矢量对象,我使用push_back 添加DataFolder 对象。第一次分配有效,但是在后续尝试中,分配时没有内存或访问问题,但所有先前存储的项目中包含的数据都已损坏。只有最近添加的内容没有改变。

如何将 DataFolder 对象添加到我的 C++ STL Vector 对象并保留先前存储在向量中的数据?

这是我创建的函数:directory_base。

#include <iostream>
#include <filesystem>
#include <ctime>
#include <vector>
#include "CDir.h"

using namespace std;
using namespace std::filesystem;

// CDIR List folder.
// CDIR NAME lists the files in a folder.NAME must be specified as a
// character vector or string scalar.
//
// NAME can include a relative path, but the relative path must be in the
// current folder.Otherwise, NAME must include a full path.
//
// To list filesand folders at a remote location, NAME must contain a
// full path specified as a uniform resource locator(URL).
//
// Pathnamesand asterisk wildcards may be used in NAME.A single asterisk
// in the path touching only file separators will represent exactly one
// folder name.A single asterisk at the end of an input will represent
// any filename.An asterisk followed or preceded by characters will
// resolve to zero or more characters.A double asterisk can only be used
// in the path and will represent zero or more folder names.It cannot
// touch a character other than a file separator.For example, DIR* .m
// lists all files with a.m extension in the current folder.DIR*/*.m
//   lists all files with a .m extension exactly one folder under the
//   current folder. CDIR **/* .m lists all files with a.m extension zero or
// more folders under the current folder.
//
// D = CDIR('NAME') returns the results in an M - by - 1
// structure with the fields :
// name        -- Filename
// folder      -- Absolute path
// date        -- Modification date
// bytes       -- Number of bytes allocated to the file
// isdir-- 1 if name is a folder and 0 if not
// datenum     -- Modification date as a MATLAB serial date number.
// This value is locale - dependent.
//
// See also WHAT, CD, TYPE, DELETE, LS, RMDIR, MKDIR, DATENUM.

// Copyright 1984 - 2019 The MathWorks, Inc.
// Built - in function.

static const char* convertIntToMonth(int imon)
{
    if (imon == 1)
    {
        return "Jan";
    }
    else if (imon == 2)
    {
        return "Feb";
    }
    else if (imon == 3)
    {
        return "Mar";
    }
    else if (imon == 4)
    {
        return "Apr";
    }
    else if (imon == 5)
    {
        return "May";
    }
    else if (imon == 6)
    {
        return "Jun";
    }
    else if (imon == 7)
    {
        return "Jul";
    }
    else if (imon == 8)
    {
        return "Aug";
    }
    else if (imon == 9)
    {
        return "Sep";
    }
    else if (imon == 10)
    {
        return "Oct";
    }
    else if (imon == 11)
    {
        return "Nov";
    }
    else if (imon == 12)
    {
        return "Dec";
    }
    else if (imon < 1 || imon > 12)
    {
        return "OOR";
    }

    return "INV";
}

static double dateNumber(double year, int month, double day)
{
    double cumdays[] = { 0, 0,31,59,90,120,151,181,212,243,273,304,334 };
    double retval = 365 * year + cumdays[month] + day;
    retval += year / 4;
    return retval;
}

const vector<DataFolder>& directory_base(const char* path, vector<DataFolder>& datfldr)
{
    int ii = 0;
    
    cout << "Let put out the files!" << endl;
    for (recursive_directory_iterator i(path), end; i != end; ++i)
    {
        if (!is_directory(i->path()))
        {
            if (is_regular_file(i->path()))
            {
                DataFolder df{};
                filesystem::path df_name = i->path();
                string fn = df_name.string();
                df.name = new char[fn.length()];
                df.name = const_cast<char*>(fn.c_str());
                struct stat attrib {};
                struct tm *clock = new tm();
                stat(df.name, &attrib);
                errno_t errNo = localtime_s(clock, &(attrib.st_mtime));
                size_t fsz = file_size(df.name);
                df.bytes = static_cast<int>(file_size(df_name));
                
                string tmp = to_string(clock->tm_mday) + "-" + 
                convertIntToMonth(clock->tm_mon+1) + "-" + to_string(clock->tm_year+1900) + " 
                " + to_string(clock->tm_hour) + ":" + to_string(clock->tm_min) + ":" + 
                to_string(clock->tm_sec);

                df.date = new char[tmp.length()];
                df.date = const_cast<char*>(tmp.c_str());
                
                df.datenum = dateNumber(static_cast<double>(clock->tm_year)+1900, clock-
                >tm_mon+1, clock->tm_mday);

                filesystem::path df_fldr = i->path().parent_path();
                string ffldr = df_fldr.string();
                df.folder = new char[ffldr.length()];
                df.folder = const_cast<char*>(ffldr.c_str());
                df.isdir = false;
                
                cout << i->path().filename() << "\n";
                
                cout << "\nData Folder Values" << endl;
                cout << "df.name:       " << df.name << endl;
                cout << "df.date:       " << df.date << endl;
                cout << "df.bytes:      " << df.bytes << endl;
                cout << "df.datenum:    " << df.datenum << endl;
                cout << "df.folder:     " << df.folder << endl;
                cout << "df.df.isdir:   " << df.isdir << endl;
                datfldr.push_back(df);
            }
        }
    }

    return datfldr;
}

我希望数据看起来像这样:

预期数据文件夹存储结果

相反,我得到了这个:

实际数据文件夹存储结果

感谢您的时间和帮助。

c++ vector corruption push-back
1个回答
0
投票

问题是这三行:

string ffldr = df_fldr.string();
df.folder = new char[ffldr.length()];
df.folder = const_cast<char*>(ffldr.c_str());

第一行创建一个本地对象,一旦

if (is_regular_file(i->path()))
块结束,该对象将超出范围并被销毁。

第二行为

ffldr.length()
减去 1 字符的字符串分配内存,因为 C 样式字符串字符数组需要空间来容纳空终止符。

第三行覆盖您刚刚创建的指针,丢失您分配的内存。一旦区块结束,指针也会失效,

ffldr
的生命周期结束。

自然的 C++ 解决方案当然是使

DataFolder::folder
成为
std::string

如果由于某种原因不能这样,您首先需要分配

ffldr.length() + 1
字符并使用
std::strcpy
copy 字符串。

© www.soinside.com 2019 - 2024. All rights reserved.