I fired up the search engines but cannot find a corresponding answer to my problem:
Basically I want to have a map, each entry containing a list of structs.
A struct itself contains 2 std::string variables and a std::list<string>.
Everything works as expected, despite accessing the list within the struct.
One method (here: getRules) creates a map entry if necessary and attach a list to it and add one struct (here: Rule) element to it.
Within this method another method (here: getRuleParams) is called which should take care of adding elements to the list within the struct.
Within the getRuleParams method the list with added element is directly accessible through the struct element correctly.
Within the “sourrounding” method the list with added element is directly accessible through the struct element correctly, as well.
BUT, if I want to access the struct’s list, or better it’s list elements, then weird stuff happens. I figured out, that the addresses changed (struct, list within struct….)
You can see that in the output my code produces (assuming it’s coded correctly).
Since I am new to C++, maybe I am missing something very easy/essential.
Does it have to do with some copy constructors which get called, but why is it the same behaviour with only using pointers to all “variables”?
I really hope someone here can enlighten me.
I simplified/isolated my problem as much as I could. (The signatures of the methods have to be that way e.g. void*, because I rely on other functions)
Please see code below and thanks in advance:
#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();
}
This is a significant issue all by itself:
Though I don’t necessarily advise this model, you can probably address this by:
But to do it properly, you should push a blank rule into the list, then reference that rule object (the one in the list) for initialization:
To be honest, the paradigm itself needs a bit of work, there is a lot of unnecessary
find()ing going on in here, and methodical use of references and iterators could clean this up quite a bit.Rework Example:
The following has stripped all the output clauses. They were actually making it harder to see problems. Please review the following to hopefully give you some ideas: