4

検索エンジンを起動しましたが、問題に対応する答えが見つかりません。

基本的に、マップが必要です。各エントリには構造体のリストが含まれています。構造体自体には、2つstd::stringの変数と1つのが含まれていstd::list<string>ます。

構造体内のリストにアクセスしているにもかかわらず、すべてが期待どおりに機能します。

1つのメソッド(ここではgetRules)は、必要に応じてマップエントリを作成し、それにリストを添付して、それに1つの構造体(ここではRule)要素を追加します。このメソッド内で別のメソッド(ここではgetRuleParams)が呼び出され、構造体内のリストへの要素の追加を処理する必要があります。

getRuleParamsメソッド内で、要素が追加されたリストには、struct要素を介して直接アクセスできます。「sourrounding」メソッド内では、要素が追加されたリストにも、struct要素を介して直接アクセスできます。

しかし、構造体のリストにアクセスしたい場合、またはより適切にはリスト要素にアクセスしたい場合は、奇妙なことが起こります。アドレスが変更されたことがわかりました(構造体、構​​造体内のリスト....)

あなたは私のコードが生成する出力でそれを見ることができます(それが正しくコーディングされていると仮定して)。

私はC++を初めて使用するので、非常に簡単で重要なものが欠けている可能性があります。呼び出されるいくつかのコピーコンストラクターと関係がありますが、すべての「変数」へのポインターのみを使用した場合と同じ動作になるのはなぜですか?

ここの誰かが私を啓発してくれることを本当に願っています。

私は自分の問題を可能な限り単純化/分離しました。(メソッドのシグネチャはそのようにする必要があります。たとえばvoid*、他の関数に依存しているためです)

以下のコードを参照し、事前に感謝します。

#include <list>
#include <map>
#include <string>
#include <iostream>

using namespace std;

struct Rule {
    string target;
    string action;
    list<string> params;
};

static int getRuleParams(void *prule) {
    Rule* rule = (Rule*) (prule);
    string param = "Entry!";

    //Fill struct with ruleparams
    rule->params.push_back(param);
    cout << "Method getRuleParams()\n" << "parameter: "
    << *(rule->params.begin()) << " \nadress of rule:\t\t\t" << rule
    << " \nadress of rule.params:\t\t" << &(rule->params) << std::endl
    << std::endl;
    return 0;
}

static int getRules(void *dbpolicies) {
    string policy = "FileIO";
    string target = "TARGET";
    string action = "DENY";

    std::map<std::string, std::list<Rule> >* policies = (std::map<std::string,
                                                         std::list<Rule> >*) (dbpolicies);

    //Create std::list<DBRule> (list) for Policy Map-Entry, if not existing
    if ((*policies).find(policy) == (*policies).end())
        (*policies)[policy] = std::list<Rule>();

    //Fill struct
    Rule rule = { target, action };
    (*policies).find(policy)->second.push_back(rule);

    //call Method which manipulates params in struct
    getRuleParams(&rule);

    cout << "Method getRulesforPackage() (access rule directly):";
    cout << "\nparameter = " << *(rule.params.begin())
    << "\naddress of rule:\t\t" << &rule;
    cout << "\nadress of rule.params:\t\t" << &(rule.params) << std::endl
    << std::endl;

    cout << "Method getRulesforPackage() access rule via map:" << std::endl;

    //READ params from map entry -> EVIL
    std::list<Rule> dbrules = (*policies).find(policy)->second;
    Rule firstrule = *dbrules.begin();
    std::list<std::string> dbruleparams = firstrule.params;
    string ruleparam = *(firstrule.params.begin()); //EVIL!
    //  string ruleparam = *(dbruleparams.begin()); // <- REALLY EVIL! (program crashes)

    //Variant 2: pointers only
    std::list<Rule>* dbrules2 = &(*policies).find(policy)->second;
    Rule* firstrule2 = &*(dbrules2->begin());
    std::list<std::string>* dbruleparams2 = &(firstrule2->params);


    cout << "rule.target = " << firstrule.target << "\nrule.action = "
    << firstrule.action << std::endl;
    cout << "address of rule:\t\t" << &firstrule << std::endl;
    cout << "address of rule (pointer):\t" << firstrule2 << std::endl;

    //  string ruleparam2 = *(dbruleparams2->begin()); //REALLY EVIL! (program crashes)

    //  cout << "parameter: " << ruleparam << std::endl;
    //  cout << "parameter (pointer): " << ruleparam2 << std::endl;


    return 0;
}

static std::map<std::string, std::list<Rule> > getPolicies() {
    std::map<std::string, std::list<Rule> > policies;
    getRules(&policies);
    return policies;

}

int main() {
    std::map<std::string, std::list<Rule> > policies = getPolicies();
}
4

1 に答える 1

3

これはそれ自体が重要な問題です。

Rule rule = { target, action };
(*policies).find(policy)->second.push_back(rule);

//call Method which manipulates params in struct
// **NOTE**: Fills the local variable "rule", not the one just pushed into the list
getRuleParams(&rule); 

私は必ずしもこのモデルをアドバイスするわけではありませんが、おそらく次の方法でこれに対処できます。

Rule rule = { target, action };
getRuleParams(&rule); // fill here, before the push

// then push.
(*policies).find(policy)->second.push_back(rule);

ただし、これを正しく行うには、空白のルールをリストにプッシュしてから、そのルールオブジェクト(リスト内のオブジェクト)を参照して初期化する必要があります。

Rule rule = { target, action };
(*policies)[policy].push_back(rule);
getRuleParams(&(*policies)[policy].back());

正直なところ、パラダイム自体には少し作業が必要でありfind()、ここでは不要なことがたくさん行われています。参照とイテレーターを系統的に使用すると、これをかなりクリーンアップできます。


リワークの例:

以下は、すべての出力句を削除しました。彼らは実際に問題を見つけるのを難しくしていました。うまくいけば、いくつかのアイデアを与えるために、以下を確認してください。

#include <list>
#include <map>
#include <string>
#include <iostream>

using namespace std;

// basic rule with strin parameter list
typedef std::list<std::string> ParamList;
struct Rule
{
    string target;
    string action;
    ParamList params;
};

typedef std::list<Rule> RuleList;
typedef std::map<std::string, RuleList> MapStringToRuleList;

static int getRuleParams(void *prule)
{
    Rule* rule = (Rule*) (prule);
    rule->params.push_back("Entry!");
    return 0;
}

static int getRules(void *dbpolicies) {

    string policy = "FileIO";
    string target = "TARGET";
    string action = "DENY";

    MapStringToRuleList* policies = (MapStringToRuleList*)(dbpolicies);

    // push a new rule into the list.
    Rule rule = {target, action};
    RuleList& rules = (*policies)[ policy ];
    rules.push_back(rule);

    //call Method which manipulates params in struct
    getRuleParams(&rules.back());

    // for each rule in our policy's rule list...
    for (RuleList::const_iterator rit = rules.begin(); rit != rules.end(); rit++)
    {
        cout << "Rule: " << policy << endl;

        // for each rule in our curent rule's params list
        const ParamList& params = rit->params;
        for (ParamList::const_iterator pit = params.begin(); pit != params.end(); pit++)
        {
            cout << "  Rule Param: " << *pit << endl;
            // TODO: use current param for something.
        }            
    }
    return 0;
}

static MapStringToRuleList getPolicies()
{
    MapStringToRuleList policies;
    getRules(&policies);
    return policies;
}

int main()
{
    MapStringToRuleList policies = getPolicies();
}
于 2013-01-10T04:05:13.533 に答える