矢量push_back崩溃

时间:2011-12-09 18:36:03

标签: c++ stl

我有以下结构。

#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

3 个答案:

答案 0 :(得分:2)

采用数组的构造函数让我担心。

修改

根据更新的问题:

问题是带向量的构造函数 您正在访问元素而不检查它们是否存在。

因此,如果任何输入行都不好(即并非所有值都存在),那么向量将不会像所需的那样大,并导致未定义的行为。

如果您更改这些行:

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) ) {

这里没有必要检查好()。如果流未处于良好状态,则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)
             );
}

答案 1 :(得分:2)

这是了解一些调试技术的方便之处。在您创建新station的位置,我发出了断言:

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

这可以确保您无法访问不存在的矢量元素。

另一个工具是使用向量成员at()而不是运算符[],它执行运行时索引检查并将为越界索引抛出异常:

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

答案 2 :(得分:0)

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

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

最后,正如其他人已经指出的那样,如果你只有三个参数,将向量传递给构造函数并不是一个好主意。它不仅可能产生难以捕获的错误,而且还在while循环的每次迭代中为额外的构造函数和析构函数付出代价。希望它有所帮助。