I have a vector of strings which are changing its contents for no apparent reason. Can't really explain what is going on. Sorry for a long listing, but it's really bugging me.
I have a GUI application which loads some files and uses a reader object which state can be set by using a parse(int argc, char* argv[])
method. The arguments are set in a dialog by checking various boxes and entering values. Here is a struct I use to hold the data from the dialog:
struct PointFilter
{
PointFilter(): argc(0) {};
~PointFilter() {};
int argc;
std::vector<std::string> args;
};
This struct is a member of the dialog class and after pressing ok button its populated with appropriate values. The values are taken from text boxes on the dialog into a stringstream and then pushed back into a std::vector:
class AdvancedLoadDialog
{
public:
AdvancedLoadDialog(const Glib::RefPtr<Gtk::Builder>&);
~AdvancedLoadDialog();
PointFilter get_point_filter()
{
return this->point_filter;
}
private:
PointFilter point_filter;
void on_ok_btn_clicked();
void AdvancedLoadDialog::on_ok_btn_clicked()
{
std::stringstream filter_stream;
// filter_stream << some_values_from_textboxes ...
std::vector<std::string> args;
std::string arg;
// we need a dummy first argument to emulate the command line
args.push_back("filter");
while (filter_stream >> arg)
{
args.push_back(arg);
}
point_filter.argc = args.size() > 1 ? args.size() : 0;
point_filter.args = args;
advanced_load_dialog->hide_all();
}
Everything works fine till this point and we have an AdvancedLoadDialog
object with point_filter
member which holds our arguments. Now in a separate window I take the point_filter object and pass it to a constructor of LoadWorker
class, which loads the files and also has a PointFilter
member.
load_worker = new LoadWorker(..., advanced_load_dialog->get_point_filter())
And then:
LoadWorker::LoadWorker(..., PointFilter pf) :
point_filter (pf)
All well and good. Now in the LoadWorker::run()
function I take the arguments from the point_filter, convert them into std::vector and pass them them to the `parse(int argc, char* argv[]) function I need.
void LoadWorker::run()
{
std::cout << "LoadWorker::file_filter contents: \n"
<< "point_filter.argc: " << point_filter.argc << "\n"
<< "point_filter.args: " << std::endl;
for (int i = 0; i < point_filter.argc; ++i)
std::cout << point_filter.args[i] << std::endl;
// ...
if (point_filter.argc != 0)
{
std::cout << "Using filter: " << std::endl;
std::vector<char*> argv;
for (std::vector<std::string>::const_iterator it = point_filter.args.begin();
it != point_filter.args.end(); ++it)
{
argv.push_back(const_cast<char*>(it->c_str()));
}
argv.push_back(0);
for (int i = 0; i < point_filter.argc; ++i)
{
std::cout << argv[i] << std::endl;
}
if (!lasreadopener.parse(point_filter.argc, &argv[0]))
{
send_message("Error parsing filter parameters.");
sig_fail();
return;
}
}
}
Now this works... once. You can notice that the arguments are printed twice, first as elements of LoadWorker::point_filter.args
vector and then as elements of the vector<char*> argv
. If I set the filter and then press the load button it all works. If I then try to load another file, without changing AdvancedLoadDialog::point_filter
at all, the arguments are disappearing. Here's an example output trying to load two files in a row.
LoadWorker::file_filter contents: point_filter.argc: 6 point_filter.args: filter -clip_z_above 12 -keep_intensity 11 222 Using filter: filter -clip_z_above 12 -keep_intensity 11 222 LoadWorker::file_filter contents: point_filter.argc: 6 point_filter.args: filter clip_z_above 2 keep_intensity 1 22 Using filter: filter
// 6 blank lines here
To make it even more odd, during the second run each string except the first one in point_filter.args
is missing the first character and in the argv
they are all empty.
Any clues whatsoever?