c++访问矢量的矢量得到分割错误

C++ accessing vector of vector got segmentation fault

本文关键字:分割 错误 访问 c++      更新时间:2023-10-16

我创建了一个vector(10*10000)的vector,并尝试通过成员函数访问这个vector。但我有一个分割错误。我不知道这是怎么回事…

Here is Simple.h

class Simple 
{
private:
    std::vector<double> data_row;
    std::vector<std::vector<double> > data;
public:
    Simple():data_row(10000), data(10, data_row){};
    /*initialize data vector*/
    int getSampleCounts(std::istream &File);
    /*return number of packet samples in this file*/
    Result getModel(std::istream &File);
    /*return average and variance of simple delta time*/
    void splitData (std::istream &File, const int & sample_in_fold);
};
#endif  /* SIMPLE_H */

这里是Simple.cpp

void Simple::splitData(std::istream& File, const int & sample_in_fold) {
    double value = 0.0;
    bool isFailed = true;
    int label = 0;
    while (File >> value) {
        // for each value, generate a label
        srand(time(NULL));
        label = rand() % 10; // generate label between 0 to 9
        while (isFailed) {
            // segmentation fault in the next line!
            std::cout << "current data size is: " << this->data.size() <<endl; 
            std::vector<double>::size_type sz = this->data[label].size();
            if (sz <= sample_in_fold) {
                std::cout << "current size is " << sz << "< samples in fold: " << sample_in_fold << endl;
                this->data[label].push_back(value);
                std::cout << "push_back succeed!" << endl;
                isFailed = false;
            } else {
                std::cout << "label " << label << "if full. Next label. n";
                srand(time(NULL));
                label = rand() % 10;
                sz = this->data[label].size();
            }
        }
    }
}

,我在这里附加主文件。

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> // for system())
#include <sys/types.h>
#include <dirent.h>
#include <vector>
#include <limits.h> // for PATH_MAX
#include "Complex.h"
#include "Result.h"
#include "Simple.h"
#include <math.h> 
using namespace std;
int main(int argc, char ** argv) {
    struct dirent *pDirent;
    DIR *pDir;
    std::string line;
    // check for args
    if (argc == 1) {
        printf("Usage: ./main + folder name. n");
        return 1;
    }
    pDir = opendir(argv[1]);
    if (pDir == NULL) {
        printf("Cannot open directory '%s' n", argv[1]);
        return 1;
    }
    // readdir returns a pointer to the next direcctory entry dirent structure
    while ((pDirent = readdir(pDir)) != NULL) {
        // get file name and absolute path
        char *name = pDirent->d_name;
        char buf[PATH_MAX + 1];
        realpath(name, buf);
        //        std::cout << "Current file is: " << (pDirent->d_name) << endl;
        if (has_suffix(pDirent->d_name, ".txt")) {
            printf("[%s]n", pDirent->d_name);
            //printf("absolute path is %s. n", buf);
            ifstream infile;
            // open file with absolute path
            infile.open(buf, ios::in);
            if (!infile) {
                cerr << "Can't open input file " << buf << endl;
                exit(1);
            }
            //processing for simple pattern
            if (has_suffix(name, "testfile.txt")) {
                Simple* simple_obj;
                int number = simple_obj->getSampleCounts(infile);
                Result simplerst = simple_obj->getModel(infile);
                std::cout << "Number of delta time is " << number << endl;
                infile.clear();
                infile.seekg(0);
                write_to_file(pDirent->d_name, simplerst);
                // divide data into k = 10 folds, get number of data in each fold
                int sample_in_fold = floor(number / 10);
                std::cout << sample_in_fold << std::endl;
                simple_obj->splitData(infile, sample_in_fold);
            }
        } else {
            //            printf("This is not a txt file. Continuen");
        }
    }
    closedir(pDir);
    return 0;

}

这里是一个示例testfile.txt。为了说明,我只复制了原始文件的一部分。

10.145906000
10.151063000
10.131083000
10.143461000
10.131745000
10.151285000
10.147493000
10.123198000
10.144975000
10.144484000
10.138129000
10.131634000
10.144311000
10.157710000
10.138047000
10.122754000
10.137675000
10.204973000
10.140399000
10.142194000
10.138388000
10.141669000
10.138056000
10.138679000
10.141415000
10.154170000
10.139574000
10.140207000
10.149151000
10.164629000
10.106818000
10.142431000
10.137675000
10.204973000
10.140399000
10.142194000
10.138388000
10.141669000
10.138056000
10.138679000
10.141415000

Here is Result.h

#ifndef RESULT_H
#define	RESULT_H
typedef struct Result {
    double average;
    double sigma;
}Result;

和Simple.cpp中的getModel函数:

Result Simple::getModel(std::istream &File) {
    double value = 0.0;
    double average = 0.0;
    double sum = 0.0;
    double counter = 0.0;
    double sumsqr = 0.0;
    double var = 0.0;
    double sigma = 0.0;
    while (File >> value) {
        ++counter;
        sum += value;
        sumsqr += value * value;
    }
    average = sum / counter;
    var = sumsqr / counter - average * average; //E(x^2) - (E(x))^2
    sigma = sqrt(var);
    std::cout << "average is " << average << std::endl;
    std::cout << "std deviation is " << sigma << std::endl;
    File.clear();
    File.seekg(0);
    Result result = {average, sigma};
    return result;
}

马上有一个问题:

Simple* simple_obj;
int number = simple_obj->getSampleCounts(infile);

simple_obj是一个未初始化的指针,因此程序此时显示未定义行为

为什么要使用指针呢?您可以简单地这样做来避免这个问题:

Simple simple_obj;
simple_obj.getSampleCounts(infile);

同样,这一行可能不是问题,但我还是要提到它:

Result simplerst = simple_obj->getModel(infile);

我们已经知道在你的原始代码中,simple_obj是假的,但这不是这里的问题。如果Result是一个对象,并且该对象没有正确的复制语义,那么该赋值也将导致未定义行为。

在没有指定std::endl的情况下使用了endl(它们不是同一件事-您总是必须键入std::)。endl是默默地引用另一个变量在其他地方吗?