【问题标题】:C++ accessing vector of vector got segmentation faultC ++访问向量的向量得到分段错误
【发布时间】:2015-06-04 18:18:57
【问题描述】:

我创建了一个向量(10*10000)的向量,并尝试通过成员函数访问这个向量。但我遇到了分段错误。我不知道这里出了什么问题...

这里是 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. Continue\n");
        }
    }
    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

这是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;
}

【问题讨论】:

  • 什么时候出现分段错误?是调用splitData函数的时候吗?
  • @RobinHartland 在 splitData 函数中访问 this->data.size() 时
  • vector 通常是一个糟糕的设计,除非你必须保持低内存消耗。
  • 在我的电脑上运行良好...
  • 你确定你声明 data_row 和 data 的顺序和你在这里做的一样吗?如果数据在您的完整类中的 data_row 上方定义,它将因您初始化它们的方式而中断

标签: c++ vector segmentation-fault


【解决方案1】:

马上一个问题:

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 是一个对象,并且该对象没有正确的复制语义,那么该赋值也会导致未定义的行为。

【讨论】:

  • 谢谢! Result是一个struct,而getModel函数返回一个Result的对象,所以我创建simplerst...会不会也有问题?
  • 这取决于struct 中的成员。在您的原始问题中发布 Result 结构,因为这可能是另一个问题。
  • 好的。 Result 很好。它将毫无问题地复制过来。等等——一个小问题——确保在复制之前初始化您的成员。复制未初始化的浮点变量是未定义的行为。
  • @pinteson,看起来这有助于您解决问题,所以如果您可以通过将此答案左侧的勾号变为绿色来接受此答案,这将向所有人展示这一点,并给 PaulMcKenzie他应得的额外代表
  • @RobinHartland 是的,对不起,我是新手。
【解决方案2】:

你有几个 endl 没有指定 std::endl 的用法(它们不是一回事 - 你总是必须输入 std:: )。 endl 是否在其他地方默默地引用另一个变量?

【讨论】:

  • 不...我在顶部有using namespace std,在我添加std::后问题仍然存在
  • 如果你摆脱 using namespace std?有点邪恶。
  • 你纠正了所有的 endl —— seg 故障线上的那个,cout
  • 是的,我已经删除了using namespace std 并全部替换为std::
  • 在这种情况下,你能给出一个很好的最小、完整的例子(stackoverflow.com/help/mcve)吗?它在我的机器上运行良好,在 Sean 的机器上运行良好。
猜你喜欢
  • 1970-01-01
  • 2018-08-30
  • 2019-11-10
  • 1970-01-01
  • 2020-04-19
  • 1970-01-01
  • 2023-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多