Consider the following example:
#include <iostream>
#include <sstream>
#include <vector>
#include <wchar.h>
#include <stdlib.h>
using namespace std;
struct odp {
int f;
wchar_t* pstr;
};
int main()
{
vector<odp> vec;
ostringstream ss;
wchar_t base[5];
wcscpy_s(base, L"1234");
for (int i = 0; i < 4; i++)
{
odp foo;
foo.f = i;
wchar_t loopStr[1];
foo.pstr = loopStr; // wchar_t* = wchar_t ? Why does this work?
foo.pstr[0] = base[i];
vec.push_back(foo);
}
for (vector<odp>::iterator iter = vec.begin(); iter != vec.end(); iter++)
{
cout << "Vec contains: " << iter->f << ", " << *(iter->pstr) << endl;
}
}
This produces:
Vec contains: 0, 52
Vec contains: 1, 52
Vec contains: 2, 52
Vec contains: 3, 52
I would hope that each time, iter->f and iter->pstr would yield a different result. Unfortunately, iter->pstr is always the same.
My suspicion is that each time through the loop, a new loopStr is created. Instead of copying it into the struct, I’m only copying a pointer. The location that the pointer writes to is getting overwritten.
How can I avoid this? Is it possible to solve this problem without allocating memory on the heap?
A – You allocate an array (of size 1) to the stack
B – You assign foo.pstr to point to the array on the stack
C – You assign base[i] to the first element of the array (which is on the stack)
After the for loop exits its current cycle the variable loopStr is no longer in scope and its content is undefined. The next loop iteration will most likley re-use the same memory address (hence why you get the same value when you print at the end). If you have optimisations turned on your C compiler may be able to warn you about taking addresses of local variables (although I doubt it).
Without using any heap allocation I would think your only option is to fix the size of foo.pstr in odp, i.e.
or allocate the array on the heap as part of the odp initialisation
better still use std::wstring since you are using c++, and let it do the memory allocation and management for you.