// demonstrates a bug that appears as early as GCC-4.7 to current (GCC-5.1).
// affects C++11 and C++14, but not C++98 (assuming 98's inability to elide
// the copy has the same effect as generate_strings_v2).
#include <functional>
#include <algorithm>
#include <iostream>
#include <vector>
#include <cassert>
// or using deque/list makes no difference.
using stringset = std::vector<std::string>;
// @bug strings do not share data on first reassignment of result.
stringset generate_strings_v1(int count, int length)
{
stringset set(count);
for (auto& x : set) {
x.resize(length);
std::fill(x.begin(), x.end(), 'a');
}
return set;
}
// works as expected.
stringset generate_strings_v2(int count, int length)
{
stringset set(count);
for (auto& x : set) {
x.resize(length);
std::fill(x.begin(), x.end(), 'a');
}
return stringset(set);
}
// works as expected.
stringset generate_strings_v3(int count, int length)
{
stringset set;
for (int i = 0; i < count; i++) {
std::string x;
x.resize(length);
std::fill(x.begin(), x.end(), 'a');
set.push_back(x);
}
return set;
}
// works as expected.
stringset generate_strings_v4(int count, int length)
{
stringset set(count);
for (auto& x : set)
x.resize(length, 'a');
return set;
}
void test(const char* header, std::function<stringset(int, int)> genstrings,
int count, int length)
{
auto data_ptr_eq = [](const std::string& a, const std::string& b)
{
return a.data() == b.data();
};
stringset a = genstrings(count, length);
stringset b = a;
if (std::equal(a.begin(), a.end(), b.begin(), data_ptr_eq))
std::cout << header << " : data pointer match\n";
else {
std::cout << header << " : data pointer mismatch\n";
assert(a == b); // not expected; just in case.
}
}
int main(int argc, char* argv[])
{
int count = 1, length = 1;
assert(length > 0 && count > 0);
// v1
// @bug string data is not shared on first reassignment.
test("v1", generate_strings_v1, count, length);
// v2, v3, v4 work as expected.
test("v2", generate_strings_v2, count, length);
test("v3", generate_strings_v3, count, length);
test("v4", generate_strings_v4, count, length);
return 0;
}
Ly8gZGVtb25zdHJhdGVzIGEgYnVnIHRoYXQgYXBwZWFycyBhcyBlYXJseSBhcyBHQ0MtNC43IHRvIGN1cnJlbnQgKEdDQy01LjEpLgovLyBhZmZlY3RzIEMrKzExIGFuZCBDKysxNCwgYnV0IG5vdCBDKys5OCAoYXNzdW1pbmcgOTgncyBpbmFiaWxpdHkgdG8gZWxpZGUKLy8gdGhlIGNvcHkgaGFzIHRoZSBzYW1lIGVmZmVjdCBhcyBnZW5lcmF0ZV9zdHJpbmdzX3YyKS4KCiNpbmNsdWRlIDxmdW5jdGlvbmFsPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxjYXNzZXJ0PgoKLy8gb3IgdXNpbmcgZGVxdWUvbGlzdCBtYWtlcyBubyBkaWZmZXJlbmNlLgp1c2luZyBzdHJpbmdzZXQgPSBzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz47CgovLyBAYnVnIHN0cmluZ3MgZG8gbm90IHNoYXJlIGRhdGEgb24gZmlyc3QgcmVhc3NpZ25tZW50IG9mIHJlc3VsdC4Kc3RyaW5nc2V0IGdlbmVyYXRlX3N0cmluZ3NfdjEoaW50IGNvdW50LCBpbnQgbGVuZ3RoKQp7CglzdHJpbmdzZXQgc2V0KGNvdW50KTsKCWZvciAoYXV0byYgeCA6IHNldCkgewoJCXgucmVzaXplKGxlbmd0aCk7CgkJc3RkOjpmaWxsKHguYmVnaW4oKSwgeC5lbmQoKSwgJ2EnKTsKCX0KCXJldHVybiBzZXQ7Cn0KCi8vIHdvcmtzIGFzIGV4cGVjdGVkLgpzdHJpbmdzZXQgZ2VuZXJhdGVfc3RyaW5nc192MihpbnQgY291bnQsIGludCBsZW5ndGgpCnsKCXN0cmluZ3NldCBzZXQoY291bnQpOwoJZm9yIChhdXRvJiB4IDogc2V0KSB7CgkJeC5yZXNpemUobGVuZ3RoKTsKCQlzdGQ6OmZpbGwoeC5iZWdpbigpLCB4LmVuZCgpLCAnYScpOwoJfQoJcmV0dXJuIHN0cmluZ3NldChzZXQpOwp9CgovLyB3b3JrcyBhcyBleHBlY3RlZC4Kc3RyaW5nc2V0IGdlbmVyYXRlX3N0cmluZ3NfdjMoaW50IGNvdW50LCBpbnQgbGVuZ3RoKQp7CglzdHJpbmdzZXQgc2V0OwoJZm9yIChpbnQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CgkJc3RkOjpzdHJpbmcgeDsKCQl4LnJlc2l6ZShsZW5ndGgpOwoJCXN0ZDo6ZmlsbCh4LmJlZ2luKCksIHguZW5kKCksICdhJyk7CgkJc2V0LnB1c2hfYmFjayh4KTsKCX0KCXJldHVybiBzZXQ7Cn0KCi8vIHdvcmtzIGFzIGV4cGVjdGVkLgpzdHJpbmdzZXQgZ2VuZXJhdGVfc3RyaW5nc192NChpbnQgY291bnQsIGludCBsZW5ndGgpCnsKCXN0cmluZ3NldCBzZXQoY291bnQpOwoJZm9yIChhdXRvJiB4IDogc2V0KQoJCXgucmVzaXplKGxlbmd0aCwgJ2EnKTsKCXJldHVybiBzZXQ7Cn0KCnZvaWQgdGVzdChjb25zdCBjaGFyKiBoZWFkZXIsIHN0ZDo6ZnVuY3Rpb248c3RyaW5nc2V0KGludCwgaW50KT4gZ2Vuc3RyaW5ncywKCWludCBjb3VudCwgaW50IGxlbmd0aCkKewoJYXV0byBkYXRhX3B0cl9lcSA9IFtdKGNvbnN0IHN0ZDo6c3RyaW5nJiBhLCBjb25zdCBzdGQ6OnN0cmluZyYgYikKCXsKCQlyZXR1cm4gYS5kYXRhKCkgPT0gYi5kYXRhKCk7Cgl9OwoJCglzdHJpbmdzZXQgYSA9IGdlbnN0cmluZ3MoY291bnQsIGxlbmd0aCk7CglzdHJpbmdzZXQgYiA9IGE7CgkKCWlmIChzdGQ6OmVxdWFsKGEuYmVnaW4oKSwgYS5lbmQoKSwgYi5iZWdpbigpLCBkYXRhX3B0cl9lcSkpCgkJc3RkOjpjb3V0IDw8IGhlYWRlciA8PCAiIDogZGF0YSBwb2ludGVyIG1hdGNoXG4iOwoJZWxzZSB7CgkJc3RkOjpjb3V0IDw8IGhlYWRlciA8PCAiIDogZGF0YSBwb2ludGVyIG1pc21hdGNoXG4iOwoJCWFzc2VydChhID09IGIpOyAvLyBub3QgZXhwZWN0ZWQ7IGp1c3QgaW4gY2FzZS4KCX0KfQoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIqIGFyZ3ZbXSkKewoJaW50IGNvdW50ID0gMSwgbGVuZ3RoID0gMTsKCWFzc2VydChsZW5ndGggPiAwICYmIGNvdW50ID4gMCk7CgoJLy8gdjEKCS8vIEBidWcgc3RyaW5nIGRhdGEgaXMgbm90IHNoYXJlZCBvbiBmaXJzdCByZWFzc2lnbm1lbnQuCgl0ZXN0KCJ2MSIsIGdlbmVyYXRlX3N0cmluZ3NfdjEsIGNvdW50LCBsZW5ndGgpOwoJCgkvLyB2MiwgdjMsIHY0IHdvcmsgYXMgZXhwZWN0ZWQuCgl0ZXN0KCJ2MiIsIGdlbmVyYXRlX3N0cmluZ3NfdjIsIGNvdW50LCBsZW5ndGgpOwoJdGVzdCgidjMiLCBnZW5lcmF0ZV9zdHJpbmdzX3YzLCBjb3VudCwgbGVuZ3RoKTsKCXRlc3QoInY0IiwgZ2VuZXJhdGVfc3RyaW5nc192NCwgY291bnQsIGxlbmd0aCk7CglyZXR1cm4gMDsKfQ==