消失的std :: vector <std :: string> </std :: string>的内容

时间:2012-06-27 12:11:22

标签: c++ multithreading stdvector stringstream stdstring

我有一个字符串向量,它们正在改变它的内容,没有明显的原因。无法真正解释发生了什么。很抱歉很长一段时间,但这真的让我烦恼。

我有一个GUI应用程序,它加载一些文件并使用一个reader对象,可以使用parse(int argc, char* argv[])方法设置状态。通过选中各种框并输入值,在对话框中设置参数。这是一个用于保存对话框数据的结构:

struct PointFilter
{
    PointFilter(): argc(0) {};
    ~PointFilter() {};
    int argc;
    std::vector<std::string> args;
};

此结构是对话框类的成员,按下确定按钮后,其中填充了适当的值。这些值从对话框中的文本框中获取到字符串流中,然后推回到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();
}

到目前为止,一切正常,我们有一个AdvancedLoadDialog对象,point_filter成员持有我们的论点。现在在一个单独的窗口中,我获取point_filter对象并将其传递给LoadWorker类的构造函数,该构造函数加载文件并且还有PointFilter成员。

load_worker = new LoadWorker(..., advanced_load_dialog->get_point_filter())

然后:

LoadWorker::LoadWorker(..., PointFilter pf) :
    point_filter    (pf)

一切都很好。现在在LoadWorker::run()函数中,我从point_filter获取参数,将它们转换为std :: vector并将它们传递给我需要的`parse(int argc,char * argv [])函数。

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

现在这个工作......一次。您可以注意到参数被打印两次,首先是LoadWorker::point_filter.args向量的元素,然后是vector<char*> argv的元素。如果我设置过滤器,然后按下加载按钮,则一切正常。如果我然后尝试加载另一个文件,而根本不更改AdvancedLoadDialog::point_filter,则参数正在消失。这是一个尝试连续加载两个文件的示例输出。

  

LoadWorker :: file_filter内容:point_filter.argc:6   point_filter.args:过滤器   -clip_z_above 12   -keep_intensity 11 222使用过滤器:过滤器   -clip_z_above 12   -keep_intensity 11 222 LoadWorker :: file_filter内容:point_filter.argc:6 point_filter.args:filter clip_z_above 2   keep_intensity 1 22使用过滤器:过滤器

     

//这里有6个空行

更奇怪的是,在第二次运行中,除了point_filter.args中的第一个字符串之外的每个字符串都缺少第一个字符,而argv中的字符串都是空的。

任何线索?

2 个答案:

答案 0 :(得分:1)

在做与std::string::c_str有关的事情时要非常非常谨慎:

argv.push_back(const_cast<char*>(it->c_str()));

如果您想保留c_str提供的值,则应先将它们复制到新容器中。

如果要信任cplusplus.com(情况并非总是如此),

  

不应在程序中修改此数组中的值,只保证在下次调用字符串对象的非常量成员函数之前保持不变

虽然我无法立即从其他来源获取更多有用的信息。

答案 1 :(得分:1)

在AdvancedLoadDialog中,尝试推送已分配的arg版本而不是自动版本。您似乎正在推送对离开AdvancedDialogLoad时将被销毁的变量的引用。