ifstream - C++ getline segmentation fault, std::vector<custom class> -
i've been looking @ while in debugger while googling around, think i've stumbled upon c++ behavior i'm not familiar with. i'm going give quick outline on i'm doing , what/where problem is. i'll put code block below.
the rough outline of what's happening is:
- created custom class (logreader) handle single log file.
- logreader contains pointer ifstream (ifstream *log_file)
- the ifstream used getline() in constructor, works fine.
- the logreader placed in vector.
- the code below main.cpp using logreader directly (without vector). segfault occurs in both cases.
- logreader.advance() called. getline() used in function. segfault occurs here (commented in logreader.cpp).
thanks on c++ behaviors i'm missing might causing this!
edit: not placing logreader
vector removes segfault (failing elsewhere now, not problem). change commenting following line out in main.cpp
readers.push_back(&label_reader);
i guess question why using std::vector causing problem.
logreader.h
#ifndef logreader #define logreader using namespace std; class logreader { private: logreader(){} // private default constructor public: ifstream *log_file; // file log read vector<int> val_locations; // offsets in line values string next_line; // next line file int current_time; // time recent reading string current_line; int next_time; // next time in file vector<string> current_vals; // current vals logreader(string log_loc, vector<int> offsets); // given file start on bool advance(int new_time); // advance log reader, return true if advanced bool has_more(); // there more in log }; #endif
logreader.cpp
// c++ imports #include <boost/algorithm/string.hpp> #include <fstream> #include <iostream> #include <string> #include <vector> // imports #include "logreader.h" #include "functions.h" using namespace std; logreader::logreader(string log_loc, vector<int> offsets){ // make file reader ifstream lf(log_loc); log_file = &lf; // pull out first line getline(*log_file, current_line); cout << current_line << endl; // set of current values val_locations = offsets; for(int = 0; < val_locations.size(); i++) { current_vals.push_back(get_line_part(current_line, val_locations.at(i))); } // current time current_time = stoi(get_line_part(current_line, 0)); // pull down next line getline(*log_file, next_line); cout << next_line << endl; // next time next_time = stoi(get_line_part(next_line, 0)); } bool logreader::advance(int new_time){ if(new_time < next_time) return false; // nothing do, current still cout << "can check time" << endl; // update time , values current_time = next_time; current_line = next_line; current_vals.clear(); cout << "can housekeeping" << endl; for(int = 0; < val_locations.size(); i++) { current_vals.push_back(get_line_part(next_line, val_locations.at(i))); } cout << "can push in new values" << endl; // move line next_line.clear(); if(!getline(*log_file, next_line)) { // **segfault** // no more lines cout << "no more lines" << endl; next_line.clear(); next_time = -1; return true; } cout << "got line" << endl; // update time next_time = stoi(get_line_part(next_line, 0)); return true; } bool logreader::has_more(){ return next_time != -1; }
main.cpp
// c imports #include <time.h> // c++ imports #include <algorithm> #include <boost/algorithm/string.hpp> #include <boost/date_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/filesystem.hpp> #include <fstream> #include <iostream> #include <string> #include <sstream> #include <vector> // imports #include "logreader.h" #include "functions.h" // custom shorter namespaces namespace bfs = boost::filesystem; // used namespaces using namespace std; void update_line(int *current_time, string *current_line, ifstream *current_file){ if(!getline(*current_file, *current_line)){ *current_time = -1; current_line->clear(); return; } try { *current_time = stoi(get_line_part(*current_line, 0)); } catch (int e) { cout << "update line, bad stoi on time" << endl; cout << *current_line << endl; throw e; } } void update_vals(vector<float*> vals, string line) { for(int = 0; < vals.size(); i++) { // offset fact first 2 time , sensor try { *(vals.at(i)) = stof(get_line_part(line, 2 + i)); } catch (int e) { cout << "update_vals, bad stof " << << endl; cout << line << endl; throw e; } } } string get_correct_file(string name, vector<string> options) { for(int =0; < options.size(); i++) { string option = options.at(i); if(boost::algorithm::contains(option, name)){ return option; } } return string(""); } int main(int argc, char* argv[]) { // open base dir bfs::path base_dir("log/"); if(!bfs::exists(base_dir) && !bfs::is_directory(base_dir)){ cout << "bad base directory" << endl; return 1; } // create vector of possible traces vector<string> traces; for(bfs::directory_iterator iter(base_dir); iter != bfs::directory_iterator(); iter++) { stringstream trace_path; trace_path << iter->path().string(); traces.push_back(trace_path.str()); } int trace_index = user_choose_option(traces); // load directory bfs::path trace_dir(traces.at(trace_index)); if(!bfs::exists(base_dir) && !bfs::is_directory(base_dir)){ cout << "selected bad trace directory" << endl; return 1; } // image directory cout << "loading image directory" << endl; string img_path_string = trace_dir.string(); stringstream img_path_stream; img_path_stream << img_path_string << "/img/"; bfs::path img_dir(img_path_stream.str()); if(!bfs::exists(img_dir) && !bfs::is_directory(img_dir)){ cout << "no image directory" << endl; return 1; } // image list, ends in sorted order naming conventions cout << "getting image paths" << endl; vector<string> image_paths; for(bfs::directory_iterator iter(img_dir); iter != bfs::directory_iterator(); iter++) { stringstream image_path; image_path << iter->path().string(); image_paths.push_back(image_path.str()); } // data traces cout << "loading data traces" << endl; vector<string> log_paths; vector<string> label_paths; string trace_path_string = trace_dir.string(); for(bfs::directory_iterator iter(trace_path_string); iter != bfs::directory_iterator(); iter++) { string cur_file = iter->path().string(); cout << cur_file << endl; if(boost::algorithm::contains(cur_file, "label-")) { label_paths.push_back(cur_file); } else if(boost::algorithm::contains(cur_file, "log-")) { log_paths.push_back(cur_file); } } cout << endl; // temp reading in line parts // istringstream temp; cout << "getting log readers" << endl; // choose label file use, first line int label_index = user_choose_option(label_paths); vector<int> label_offsets; label_offsets.push_back(1); logreader label_reader(label_paths.at(label_index), label_offsets); /* ifstream label_file(label_paths.at(label_index)); string label_line; getline(label_file, label_line); int label_time; temp.clear(); temp.str(get_line_part(label_line, 0)); temp >> label_time; string label_current = get_line_part(label_line, 1); */ /* // accel string accel_path = get_correct_file("accel", log_paths); vector<int> accel_offsets; accel_offsets.push_back(2); accel_offsets.push_back(3); accel_offsets.push_back(4); logreader accel_reader(accel_path, accel_offsets); */ vector<logreader*> readers; vector<bool> updated; readers.push_back(&label_reader); updated.push_back(true); // readers.push_back(&accel_reader); // updated.push_back(true); int l_time = current_time_min(readers); while(label_reader.has_more() ){ // || accel_reader.has_more()) { // figure out time advance int n_time; cout << label_reader.has_more() << endl; if(same_current_time(readers)) { n_time = next_time_min(readers); } else { n_time = current_time_nextmin(readers); } cout << n_time << endl; label_reader.advance(n_time); cout << label_reader.current_line << endl; /* // advance readers for(int = 0; < readers.size(); i++) { cout << "loop " << << endl; // keep track of values updated readers.at(i); cout << "can vector" << endl; bool advanced = readers.at(i)->advance(n_time); cout << advanced << endl; if(advanced) { updated.at(i) = true; } else { updated.at(i) = false; } } // sanity check printing for(int = 0; < readers.size(); i++) { cout << readers.at(i)->current_line << endl; } */ // deal statistics here } /* ifstream accel_file(accel_path); string accel_line; getline(accel_file, accel_line); int accel_time; temp.clear(); temp.str(get_line_part(accel_line, 0)); temp >> accel_time; float accel_current_x = stof(get_line_part(accel_line, 2)); float accel_current_y = stof(get_line_part(accel_line, 3)); float accel_current_z = stof(get_line_part(accel_line, 4)); vector<float*> accel_vals; accel_vals.push_back(&accel_current_x); accel_vals.push_back(&accel_current_y); accel_vals.push_back(&accel_current_z); // sprox string sprox_path = get_correct_file("sprox", log_paths); ifstream sprox_file(sprox_path); string sprox_line; getline(sprox_file, sprox_line); int sprox_time; temp.clear(); temp.str(get_line_part(sprox_line, 0)); temp >> sprox_time; float sprox_current = stof(get_line_part(sprox_line, 2)); vector<float*> sprox_vals; sprox_vals.push_back(&sprox_current); // lprox string lprox_path = get_correct_file("lprox", log_paths); ifstream lprox_file(lprox_path); string lprox_line; getline(lprox_file, lprox_line); int lprox_time; temp.clear(); temp.str(get_line_part(lprox_line, 0)); temp >> lprox_time; float lprox_current = stof(get_line_part(lprox_line, 2)); vector<float*> lprox_vals; lprox_vals.push_back(&lprox_current); // light string light_path = get_correct_file("light", log_paths); ifstream light_file(light_path); string light_line; getline(light_file, light_line); int light_time; temp.clear(); temp.str(get_line_part(light_line, 0)); temp >> light_time; float light_current = stof(get_line_part(light_line, 2)); vector<float*> light_vals; light_vals.push_back(&light_current); */ // int time_current = min(label_time, min(sprox_time, // min(lprox_time, min(accel_time, // light_time)))); /* // variables processing here int total_time = 0; map<string, int> label_counts; while(label_time != -1 || accel_time != -1 || sprox_time != -1 || lprox_time != -1 || light_time != -1) { time_current++; if(label_time != -1 && time_current > label_time) { update_line(&label_time, &label_line, &label_file); if(label_line.size() > 0) // if last label, don't overwrite label_current = get_line_part(label_line, 1); } if(accel_time != -1 && time_current > accel_time) { update_line(&accel_time, &accel_line, &accel_file); if(accel_line.size() > 0) // if last line, don't overwrite update_vals(accel_vals, accel_line); } if(sprox_time != -1 && time_current > sprox_time) { update_line(&sprox_time, &sprox_line, &sprox_file); if(sprox_line.size() > 0) // if last line, don't overwrite update_vals(sprox_vals, sprox_line); } if(lprox_time != -1 && time_current > lprox_time) { update_line(&lprox_time, &lprox_line, &lprox_file); if(lprox_line.size() > 0) // if last line, don't overwrite update_vals(lprox_vals, lprox_line); } if(light_time != -1 && time_current > light_time) { update_line(&light_time, &light_line, &light_file); if(light_line.size() > 0) // if last line, don't overwrite update_vals(light_vals, light_line); } // processing happens here total_time++; if(label_counts.count(label_current) == 0) // not in map label_counts[label_current] = 0; label_counts[label_current]++; } // post processing happens here cout << "labels counts:" << endl; for(map<string, int>::iterator = label_counts.begin(); != label_counts.end(); it++) { cout << it->first << " -> " << it->second << " -> "; cout << 1.0 * it->second / total_time << endl; } */ }
your program exhibits undefined behavior since using pointer object has been deleted.
ifstream lf(log_loc); log_file = &lf;
if
gets deleted when constructor returns , still holding on pointer object.
change log_file
object instead of pointer.
Comments
Post a Comment