C++ getline 分段错误,std::vector<custom class>
C++ getline segmentation fault, std::vector<custom class>
我在谷歌搜索时在调试器中查看了一段时间,但我认为我偶然发现了一些我不熟悉的 C++ 行为。我将简要概述一下我在做什么,what/where 问题是什么。我将代码块放在下面。
正在发生的事情的大致轮廓是:
- 创建了自定义 class (LogReader) 来处理单个日志文件。
- LogReader 包含一个指向 ifstream 的指针 (ifstream *log_file)
- ifstream 在构造函数中与 getline() 一起使用,效果很好。
- LogReader 被放置在一个向量中。
- 下面 main.cpp 的代码直接使用了 LogReader(没有向量)。段错误在两种情况下都会发生。
- LogReader.advance() 被调用。此函数中使用了 getline()。段错误发生在这里(在 LogReader.cpp 中注释)。
感谢您就我遗漏的可能导致此问题的 C++ 行为提供任何帮助!
编辑:不将 LogReader
放入向量中会消除段错误(现在在其他地方失败,但不是问题)。更改是在 main.cpp
中注释以下行
readers.push_back(&label_reader);
我想现在的问题是为什么使用 std::vector 会导致这个问题。
LogReader.h
#ifndef LOGREADER
#define LOGREADER
using namespace std;
class LogReader {
private:
LogReader(){} // private default constructor
public:
ifstream *log_file; // file the log is read from
vector<int> val_locations; // offsets in line for values
string next_line; // next line from the file
int current_time; // time for most recent reading
string current_line;
int next_time; // what is the next time in the file
vector<string> current_vals; // what the current vals are
LogReader(string log_loc, vector<int> offsets); // given a file to start on
bool advance(int new_time); // advance the log reader, return true if advanced
bool has_more(); // is there more in the log
};
#endif
LogReader.cpp
// c++ imports
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
// my imports
#include "LogReader.h"
#include "functions.h"
using namespace std;
LogReader::LogReader(string log_loc, vector<int> offsets){
// make the file reader
ifstream lf(log_loc);
log_file = &lf;
// pull out the first line
getline(*log_file, current_line);
cout << current_line << endl;
// get the set of current values
val_locations = offsets;
for(int i = 0; i < val_locations.size(); i++) {
current_vals.push_back(get_line_part(current_line,
val_locations.at(i)));
}
// get the current time
current_time = stoi(get_line_part(current_line, 0));
// pull down the next line
getline(*log_file, next_line);
cout << next_line << endl;
// get the 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 to do, current still good
cout << "can check time" << endl;
// update the time and values
current_time = next_time;
current_line = next_line;
current_vals.clear();
cout << "can do housekeeping" << endl;
for(int i = 0; i < 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 the 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 the line" << endl;
// update the time as well
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>
// my 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 i = 0; i < vals.size(); i++) {
// offset for fact that first two are time and sensor
try {
*(vals.at(i)) = stof(get_line_part(line, 2 + i));
} catch (int e) {
cout << "update_vals, bad stof for " << i << endl;
cout << line << endl;
throw e;
}
}
}
string get_correct_file(string name, vector<string> options) {
for(int i =0; i < 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 the 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 a vector of the 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 that directory
bfs::path trace_dir(traces.at(trace_index));
if(!bfs::exists(base_dir) && !bfs::is_directory(base_dir)){
cout << "Selected a bad trace directory" << endl;
return 1;
}
// get the 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;
}
// get image list, ends up in sorted order from 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());
}
// get the 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 for reading in line parts
// istringstream temp;
cout << "getting log readers" << endl;
// choose the label file to use, get 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);
*/
/*
// get the 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 what time to advance to
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 all the readers
for(int i = 0; i < readers.size(); i++) {
cout << "loop " << i << endl;
// keep track of which values updated
readers.at(i);
cout << "can get from 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 i = 0; i < readers.size(); i++) {
cout << readers.at(i)->current_line << endl;
}
*/
// deal with 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);
// get the 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);
// get the 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);
// get the 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 for 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 it = label_counts.begin();
it != label_counts.end(); it++) {
cout << it->first << " -> " << it->second << " -> ";
cout << 1.0 * it->second / total_time << endl;
}
*/
}
您的程序表现出未定义的行为,因为您使用的是指向已删除对象的指针。
ifstream lf(log_loc);
log_file = &lf;
if
在构造函数 returns 时被删除,而您仍然持有指向对象的指针。
将 log_file
更改为对象而不是指针。
我在谷歌搜索时在调试器中查看了一段时间,但我认为我偶然发现了一些我不熟悉的 C++ 行为。我将简要概述一下我在做什么,what/where 问题是什么。我将代码块放在下面。
正在发生的事情的大致轮廓是:
- 创建了自定义 class (LogReader) 来处理单个日志文件。
- LogReader 包含一个指向 ifstream 的指针 (ifstream *log_file)
- ifstream 在构造函数中与 getline() 一起使用,效果很好。
- LogReader 被放置在一个向量中。
- 下面 main.cpp 的代码直接使用了 LogReader(没有向量)。段错误在两种情况下都会发生。
- LogReader.advance() 被调用。此函数中使用了 getline()。段错误发生在这里(在 LogReader.cpp 中注释)。
感谢您就我遗漏的可能导致此问题的 C++ 行为提供任何帮助!
编辑:不将 LogReader
放入向量中会消除段错误(现在在其他地方失败,但不是问题)。更改是在 main.cpp
readers.push_back(&label_reader);
我想现在的问题是为什么使用 std::vector 会导致这个问题。
LogReader.h
#ifndef LOGREADER
#define LOGREADER
using namespace std;
class LogReader {
private:
LogReader(){} // private default constructor
public:
ifstream *log_file; // file the log is read from
vector<int> val_locations; // offsets in line for values
string next_line; // next line from the file
int current_time; // time for most recent reading
string current_line;
int next_time; // what is the next time in the file
vector<string> current_vals; // what the current vals are
LogReader(string log_loc, vector<int> offsets); // given a file to start on
bool advance(int new_time); // advance the log reader, return true if advanced
bool has_more(); // is there more in the log
};
#endif
LogReader.cpp
// c++ imports
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
// my imports
#include "LogReader.h"
#include "functions.h"
using namespace std;
LogReader::LogReader(string log_loc, vector<int> offsets){
// make the file reader
ifstream lf(log_loc);
log_file = &lf;
// pull out the first line
getline(*log_file, current_line);
cout << current_line << endl;
// get the set of current values
val_locations = offsets;
for(int i = 0; i < val_locations.size(); i++) {
current_vals.push_back(get_line_part(current_line,
val_locations.at(i)));
}
// get the current time
current_time = stoi(get_line_part(current_line, 0));
// pull down the next line
getline(*log_file, next_line);
cout << next_line << endl;
// get the 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 to do, current still good
cout << "can check time" << endl;
// update the time and values
current_time = next_time;
current_line = next_line;
current_vals.clear();
cout << "can do housekeeping" << endl;
for(int i = 0; i < 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 the 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 the line" << endl;
// update the time as well
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>
// my 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 i = 0; i < vals.size(); i++) {
// offset for fact that first two are time and sensor
try {
*(vals.at(i)) = stof(get_line_part(line, 2 + i));
} catch (int e) {
cout << "update_vals, bad stof for " << i << endl;
cout << line << endl;
throw e;
}
}
}
string get_correct_file(string name, vector<string> options) {
for(int i =0; i < 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 the 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 a vector of the 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 that directory
bfs::path trace_dir(traces.at(trace_index));
if(!bfs::exists(base_dir) && !bfs::is_directory(base_dir)){
cout << "Selected a bad trace directory" << endl;
return 1;
}
// get the 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;
}
// get image list, ends up in sorted order from 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());
}
// get the 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 for reading in line parts
// istringstream temp;
cout << "getting log readers" << endl;
// choose the label file to use, get 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);
*/
/*
// get the 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 what time to advance to
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 all the readers
for(int i = 0; i < readers.size(); i++) {
cout << "loop " << i << endl;
// keep track of which values updated
readers.at(i);
cout << "can get from 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 i = 0; i < readers.size(); i++) {
cout << readers.at(i)->current_line << endl;
}
*/
// deal with 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);
// get the 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);
// get the 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);
// get the 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 for 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 it = label_counts.begin();
it != label_counts.end(); it++) {
cout << it->first << " -> " << it->second << " -> ";
cout << 1.0 * it->second / total_time << endl;
}
*/
}
您的程序表现出未定义的行为,因为您使用的是指向已删除对象的指针。
ifstream lf(log_loc);
log_file = &lf;
if
在构造函数 returns 时被删除,而您仍然持有指向对象的指针。
将 log_file
更改为对象而不是指针。