1

I was just messing around with passing pointers to functions to wrap my head around how it works and I came across some behavior that was unexpected. I have the following code:

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cmath>
#include <iomanip>

using namespace std;

struct t
{
    string x;
    string y;
};

void foo(t*);

int main()
{

    t* ts = new t[2];
    ts[0].x = "t1.x";
    ts[0].y = "t1.y";
    ts[1].x = "t2.x";
    ts[1].y = "t2.y";

    foo(ts); 

    cout << ts[0].x << endl;

}

void foo(t* s)
{
    delete[] s;
    s = new t[2];
    s[0].x = "FOO.X";
    s[1].y = "FOO.Y";
}

The output here, interestingly enough, is "FOO.X". I expected that since inside of foo, s is a copy of the pointer ts that when I delete[] s I effectively delete[] ts as they both point to the same address. Then s = new t[2]; should have no effect on ts. After foo returns, I should no longer have access to s or the array it points to and ts should point to who knows where. Am I missing somehthing?

Note: This is just a test project that I made where I constantly write and erase blocks of code to test different concepts. All the includes and using namespace std is for ease of use, and it is NOT code that I am writing for any sort of practical use, purely educational. Also, I am using MS VS 2013.

MikeRizzle
  • 84
  • 7
  • You seem to already know you obliterate the data pointed to by `ts` in `main()` (and create a memory leak in the process, btw). So is your question why invoking *undefined behavior* by still trying to use that address seems to work? – WhozCraig May 31 '15 at 03:19
  • 1
    We really need a canonical dupe for "why didn't undefined behavior do what I expected". – user2357112 May 31 '15 at 03:20
  • you should `delete [] ts;` – Andreas DM May 31 '15 at 03:21
  • 1
    @user2357112 if only it were that simple. Trying to define undefinable is a tough draw. There are a few out there that are pretty good, though. – WhozCraig May 31 '15 at 03:22
  • [Very near duplicate](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope), with an answer applicable to this question despite the differences. – user2357112 May 31 '15 at 03:22
  • @user2357112 I wasn't expecting it to do anything, I was expecting it not to do what it did, leading me to believe that there may be something I didn't learn yet that caused this. Thank you for the link to the other question, it did come close to answering mine. Anyway you guys can all chill out now. – MikeRizzle May 31 '15 at 04:20

1 Answers1

1

Try changing your foo() like this and see the result:

void foo(t* s)
{
  delete[] s;

  // Additional memory allocation
  t* u = new t[2];

  s = new t[2];
  s[0].x = "FOO.X";
  s[1].y = "FOO.Y";
}

By adding another memory allocation, I moved s to another location in the memory, which is not anymore overlapping with ts. Otherwise, s was simply allocated at the same location where ts previously resided.

As pointed out in the comments, you are observing an undefined behavior, which you should by no means rely on. The example above illustrates that pretty well.

Andrzej Pronobis
  • 33,828
  • 17
  • 76
  • 92