1

I declared a struct like this, and the following data structures

struct piece{
  int start, height, end;

  piece(int a, int b, int c){
    start = a;  height = b; end = c;
  }

};

vector<piece> piecesTog;
map <int,piece*> data;

Then, when I read the elements I do this:

while(scanf("%d %d %d", &aux1, &aux2, &aux3) != EOF){
    piecesTog.push_back( piece(aux1, aux2, aux3) );
    data[a] = data[c] = &piecesTog[tam];
}

Well, until now, I have had no problem. However, later in the program, I have to use the piece* part, to do so, I use an iterator like this

 for(map< int, piecesTog* >::iterator it = data.begin(); it != data.end(); it++){
    piece* aux = it->second;
    ...
 }

I want to have access to the structure that the it->second points, but I tried everything and nothing worked.

I printed the memory adress of it->second and &piecesTog[tam] and they are the same, but when I do (*aux).height or it->second->height they give number completely crazy, probably some trash.

I have no clue why that is happening.

If anyone has any idea how to fix it, I would appreciate it.

FY Gamer
  • 197
  • 1
  • 1
  • 9
  • `while(scanf("%d %d %d", &aux1, &aux2, &aux3) != EOF)` completely ignores everything that can go wrong except EOF, potentially leading to an infinite loop of garbage-reading. You want to make certain `scanf` read 3 values each and every time and when it didn't, that's when you want to check EOF – user4581301 Oct 27 '18 at 00:11
  • 2
    Since this is tagged C++, why are you using `scanf` anyway? There are better options like `while(std::cin >> aux1 >> aux2 >> aux3)` – user4581301 Oct 27 '18 at 00:13
  • yuo cant do it coz it's really a class and this iterator brings no object with it. You could try `auto iterr = data.begin()` instead , with some(few) chances. – Алексей Неудачин Oct 27 '18 at 01:23

1 Answers1

3
while(scanf("%d %d %d", &aux1, &aux2, &aux3) != EOF){
    piecesTog.push_back( piece(aux1, aux2, aux3) );
    data[a] = data[c] = &piecesTog[tam];
}

is almost certainly not following the Iterator invalidation rules.

piecesTog.push_back( piece(aux1, aux2, aux3) );

can trigger a resize which typically creates a new datastore, copies the elements from the old data store to the new one and then deletes the old datastore, leaving the pointers cached by

data[a] = data[c] = &piecesTog[tam];

dangling. When you use those pointers some time in the future, Ka-Blammo! Undefined Behaviour and an easily identified crash if you're lucky.

Insufficient information has been provided to supply a definitive solution, but here are a few general alternatives (in order of attractiveness):

If you know ahead of time the number of pieces that will go into piecesTog, you can reserve storage to eliminate the need to resize the vector.

If elements are only added to the end of the vector and no elements are ever removed, you can store the indexes of the elements rather than pointers to them. If the ordering never changes, the indexes will always refer to the correct elements no matter how many more items are added.

If it is possible to do so, rewrite the reader to load all of the pieces into piecesTog and then build the maps.

The above options all assume that piecesTog is assembled all at once and then left alone. If your insertion is more free-form, you sort the structure or you remove elements, you'll need to use a data structure with more favourable invalidation rules such as std::list.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
user4581301
  • 33,082
  • 7
  • 33
  • 54