矢量push_back崩溃

vector push_back crashing

本文关键字:崩溃 back push 矢量      更新时间:2023-10-16

我有以下结构:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
struct station {
    std::string id;
    std::string code;
    std::string station_name;
    station(std::vector<std::string> &in) : id(in[0]), code(in[1]), 
                                            station_name(in[2]) {}
    station(): id (""), code (""), station_name(""){}
    bool operator<( const station& rhs ) const {
        return this->station_name < rhs.station_name;   
    }
};
int main(int argc, char **argv) {    
    std::ifstream ifs(argv[1]);
    if ( ifs.peek() == EOF )  {
        exit ( 1 );
    }
    // Read the input file and update the database
    std::string line;
    station prev, current;
    std::set<station> my_set;
    while( ifs.good()&& std::getline(ifs,line) ) {
        std::stringstream  lineStream(line);
        std::string        token;
        std::vector<std::string> input;        
        while(std::getline(lineStream,token,',')) {
            input.push_back(token);
        }
        station st(input);
        my_set.insert(st);
    }
}

我正在阅读一个文件,其中包含以下格式的与railway stations相关的信息ID,Station Code,Station Name

我正在逐行读取此文件并创建station的对象,然后将其推入std::set<station>

它在一段时间后崩溃,大约在阅读21448行之后。我有大约403523

这里有什么问题

这个程序在Linux上可以正常工作,但在windows上不行

得到debug assertion failed

接受数组的构造函数使my.

编辑

基于更新后的问题:

问题在于构造函数接受一个向量。
您正在访问元素而不检查它们是否存在。

因此,如果任何一行输入是错误的(即不是所有值都存在),那么向量将不会像要求的那么大,并导致未定义的行为。

如果你改变这些行:

while(std::getline(lineStream,token,',')) {
            input.push_back(token);
        }

为:

std::getline(linestream, id,   ',');
std::getline(linestream, code, ',');
std::getline(linestream, name, ',');

然后使用这些参数调用站点构造函数(在OO代码中会很好)。那你就不会看到坠机了。一些错误检查也会很好。

注意:

while( ifs.good()&& std::getline(ifs,line) ) {

这里不需要检查good()。如果流不是处于良好状态,那么getline()将不执行任何操作。将流(getline()的返回值)转换为bool类型也会检查流的状态是否可以进一步读取,否则将转换为false(最终)。

// This is more idiomatic.
while(std::getline(ifs,line) ) {
原来

试试这个:

struct station
{
    std::string id;
    std::string code;
    std::string station_name;
    friend std::istream& operator>>(std::istream& stream, station& data)
    {
        std::string  line;
        std::getline(stream, line);
        std::stringstream  linestream(line);
        std::getline(linestream, data.id, ',');
        std::getline(linestream, data.code, ',');
        std::getline(linestream, data.station_name);
        return stream;
    }
};
int main()
{
    std::ifstream   file("station.txt");
    std::vector<station>  stations;
    std::copy(std::istream_iterator<station>(file),
              std::istream_iterator<station>(),
              std::back_inserter(stations)
             );
}

在这里了解一些调试技术是很方便的。在您创建新station的地方,我将放置一个断言:

assert(station_init_vector.size() >= 3);

这可以确保你没有访问到不存在的vector元素。

另一种方法是使用vector成员at()代替操作符[],后者执行运行时索引检查,并在索引越界时抛出异常:

station(std::vector<std::string> &in) : id(in.at(0)), code(in.at(1)),
                                        station_name(in.at(2)) {}

您的输入文件是在什么平台上创建的?c++运行时环境应该决定什么是您的平台的最佳行结束约定。所以这可能有一些问题,但这并不能解释为什么程序要等到21448行才崩溃。

你的错误信息不够丰富。通常,当断言失败时,它会显示失败的位置。在您的情况下,它似乎可能在std::vector中失败。尝试用构造函数中的at()替换[]操作符。当你试图访问一个无效的索引时,它会抛出一个超出范围的异常。

最后,正如其他人已经指出的那样,将vector传递给构造函数并不是一个好主意,特别是在只有三个实参的情况下。它不仅可能产生难以捕捉的bug,而且在每次while循环迭代中都要为额外的构造函数和析构函数付出代价。