fork download
  1. // demonstrates a bug that appears as early as GCC-4.7 to current (GCC-5.1).
  2. // affects C++11 and C++14, but not C++98 (assuming 98's inability to elide
  3. // the copy has the same effect as generate_strings_v2).
  4.  
  5. #include <functional>
  6. #include <algorithm>
  7. #include <iostream>
  8. #include <vector>
  9. #include <cassert>
  10.  
  11. // or using deque/list makes no difference.
  12. using stringset = std::vector<std::string>;
  13.  
  14. // @bug strings do not share data on first reassignment of result.
  15. stringset generate_strings_v1(int count, int length)
  16. {
  17. stringset set(count);
  18. for (auto& x : set) {
  19. x.resize(length);
  20. std::fill(x.begin(), x.end(), 'a');
  21. }
  22. return set;
  23. }
  24.  
  25. // works as expected.
  26. stringset generate_strings_v2(int count, int length)
  27. {
  28. stringset set(count);
  29. for (auto& x : set) {
  30. x.resize(length);
  31. std::fill(x.begin(), x.end(), 'a');
  32. }
  33. return stringset(set);
  34. }
  35.  
  36. // works as expected.
  37. stringset generate_strings_v3(int count, int length)
  38. {
  39. stringset set;
  40. for (int i = 0; i < count; i++) {
  41. std::string x;
  42. x.resize(length);
  43. std::fill(x.begin(), x.end(), 'a');
  44. set.push_back(x);
  45. }
  46. return set;
  47. }
  48.  
  49. // works as expected.
  50. stringset generate_strings_v4(int count, int length)
  51. {
  52. stringset set(count);
  53. for (auto& x : set)
  54. x.resize(length, 'a');
  55. return set;
  56. }
  57.  
  58. void test(const char* header, std::function<stringset(int, int)> genstrings,
  59. int count, int length)
  60. {
  61. auto data_ptr_eq = [](const std::string& a, const std::string& b)
  62. {
  63. return a.data() == b.data();
  64. };
  65.  
  66. stringset a = genstrings(count, length);
  67. stringset b = a;
  68.  
  69. if (std::equal(a.begin(), a.end(), b.begin(), data_ptr_eq))
  70. std::cout << header << " : data pointer match\n";
  71. else {
  72. std::cout << header << " : data pointer mismatch\n";
  73. assert(a == b); // not expected; just in case.
  74. }
  75. }
  76.  
  77. int main(int argc, char* argv[])
  78. {
  79. int count = 1, length = 1;
  80. assert(length > 0 && count > 0);
  81.  
  82. // v1
  83. // @bug string data is not shared on first reassignment.
  84. test("v1", generate_strings_v1, count, length);
  85.  
  86. // v2, v3, v4 work as expected.
  87. test("v2", generate_strings_v2, count, length);
  88. test("v3", generate_strings_v3, count, length);
  89. test("v4", generate_strings_v4, count, length);
  90. return 0;
  91. }
Success #stdin #stdout 0s 3476KB
stdin
Standard input is empty
stdout
v1 : data pointer mismatch
v2 : data pointer match
v3 : data pointer match
v4 : data pointer match