10

I have memory corruption in this code:

#include <string>
#include <iostream>
#include <vector>
#include <initializer_list>

int main() {
    std::vector<std::initializer_list<std::string>> lists = {
        {
            {"text1"},
            {"text2"},
            {"text3"}
        },
        {
            {"text4"},
            {"text5"}
        }
    };

    int i = 0;
    std::cout << "lists.size() = " << lists.size() << std::endl;
    for ( auto& list: lists ) {
        std::cout << "lists[" << i << "].size() = " << lists[i].size() << std::endl;
        int j = 0;
        for ( auto& string: list ) {
            std::cout << "lists[" << i << "][" << j << "] = "<< string << std::endl;
            j++;
        }
        i++;
    }
}

Sample output:

lists.size() = 2
lists[0].size() = 3
lists[0][0] = text10�j  ����text2H�j    ����text3`�j    ����text4����text5��������q

The problem is in std::initializer_list. Changing std::initializer_list to std::vector solves the problem.

The question is why memory corruption takes place with std::initializer_list?

Casey
  • 41,449
  • 7
  • 95
  • 125
Wlodzislav K.
  • 404
  • 2
  • 9
  • 26
    `std::initializer_lists` have their name for a reason. They're supposed to only be used *for initialization*, not long-term storage. That's why they have reference semantics. All your `std::initializer_list`s actually only live until the end of the initialization of `lists`. – Xeo Jul 08 '13 at 16:25
  • 6
    `^^` This comment has been officially accepted by the system as the correct answer to your question. Thank you for using our services! – Andy Prowl Jul 08 '13 at 16:34

2 Answers2

1

Because of std::string objects were destroyed before this line:

int i = 0;

If std::string has debug output in their destructors and ctors. You will be see something like: std::string::string 5 times, std::string::~string 5 times and after that

lists.size() = 2

Because of initializre_list not contain copy of std::string objects, they (temporary std::string objects0 just created and destroyed before ';'

It is for example like take reference to std::string object in such expression:

std::cout << std::string("17");

But if you replace std::string with "const char *" in your example all should works, I suppose.

fghj
  • 8,898
  • 4
  • 28
  • 56
1

Storage for initializer list is destroyed after usage, which is before line:

int i = 0;

Its details are implementation spesific, but it generally creates a dynamic array at construction and this dynamic array is destroyed at destruction.

You can find more detail at cppreference page

ergineroglu
  • 64
  • 1
  • 5