0

明らかな理由もなく内容を変更している文字列のベクトルがあります。何が起こっているのかを本当に説明することはできません。長いリストで申し訳ありませんが、それは本当に私を悩ませています.

いくつかのファイルをロードし、メソッドを使用して状態を設定できるリーダー オブジェクトを使用する GUI アプリケーションがありますparse(int argc, char* argv[])。引数は、さまざまなボックスをチェックして値を入力することにより、ダイアログで設定されます。ダイアログからのデータを保持するために使用する構造体を次に示します。

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

この構造体はダイアログ クラスのメンバーであり、[OK] ボタンを押すと、適切な値が入力されます。値は、ダイアログのテキスト ボックスから文字列ストリームに取得され、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();
}

この時点まではすべて正常に機能し、引数を保持する member を持つ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;
        }
    }
}  

これでうまくいきます...一度。引数が 2 回出力されていることがわかります。最初はLoadWorker::point_filter.argsvector の要素として、次に の要素として出力されますvector<char*> argv。フィルターを設定してからロードボタンを押すと、すべて機能します。次に、まったく変更せずに別のファイルをロードしようとするとAdvancedLoadDialog::point_filter、引数が消えます。2 つのファイルを続けてロードしようとする出力の例を次に示します。

LoadWorker::file_filter の内容: point_filter.argc: 6 point_filter.args: filter -clip_z_above 12 -keep_intensity 11 222 フィルターの使用: filter -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 行の空白行があります

さらに奇妙なことに、2 回目の実行では、最初の文字列を除く各文字列でpoint_filter.args最初の文字が欠落し、argvすべて空になります。

何か手がかりはありますか?

4

2 に答える 2

1

あなたがここでしているように、関係することをすることについて非常に、非常に注意しstd::string::c_strてください:

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

によって提供される値を保持する場合はc_str、最初にそれらを新しいコンテナーにコピーする必要があります。

cplusplus.comが信頼できる場合(常にそうであるとは限りません)、

この配列の値はプログラムで変更しないでください。文字列オブジェクトの非定数メンバー関数を次に呼び出すまで、変更されないことが保証されます。

他の情報源からのこれ以上有用な情報をすぐに手に入れることはできませんが。

于 2012-06-27T12:15:04.730 に答える
1

AdvancedLoadDialog で、自動バージョンではなく、割り当てられたバージョンの arg をプッシュしてみてください。AdvancedDialogLoad を終了すると破棄される変数への参照をプッシュしているようです。

于 2012-06-27T12:36:45.990 に答える