hpfdf's blog

By hpfdf, history, 7 years ago, In English
#include <iostream>
#include <vector>
using namespace std;

vector<int> a;

int gen(int x) {
  if (!x)
    return 0;
  int u = a.size();
  a.push_back(0);        //*/
  a[u] = gen(x - 1) + 1; /*/
  int t = gen(x - 1) + 1;
  a[u] = t;              //*/
  return a[u];
}

int main() {
  gen(10);
  for (int x : a)
    cout << x << " ";
  cout << endl;
  return 0;
}

I recently had a non-trivial bug related to std vector. Above is the simplified code to reproduce it. Semantically this should output 10 9 8 7 6 5 4 3 2 1 but actually it doesn't. The problem was here a[u] = gen(x - 1) + 1. The vector a is reallocated before gen(x - 1) finish, so the target a[u] is outdated. Adding a temp variable t resolves this bug.

Summary: be careful playing with vectors. Never do a[i] = f(), where f() could modify vector a.

  • Vote: I like it
  • +18
  • Vote: I do not like it

»
7 years ago, # |
Rev. 13   Vote: I like it 0 Vote: I do not like it

And running this code with clang(3.9.1) produces desired output: 10 9 8 7 6 5 4 3 2 1. With any optimization level. This doesn't seem to be UB, is it impementation-defined behavior?

»
7 years ago, # |
Rev. 2   Vote: I like it +16 Vote: I do not like it

Simpler example from acm.math.spbu.ru/~kunyavskiy/cpp/sol16.cpp (link):

#include <vector>
#include <iostream>

using namespace std;

vector<int> v;

int f(){
    v.push_back(1);
    return 2;
}

int main(){       
    v.push_back(0);
    v[0] = f();
    cout << v[0] <<" "<<v[1] << endl;
    return 0;
}