This question already has answers here:
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Closed 3 years ago.
I have to classes, one Employee class and one BankAccount class, the employee class has the BankAccount class as a private variable pointer.
This is what I am trying to do:
I need to set up all the BankAccounts in each Employee with values
then I delete all BankAccounts for every Employee at the end of the function.
I use a member function setter in Employee to set up the BankAccount pointer. BankAccount has one private variable and that is amount. Later I call delete on a pointer that should point to each BankAccount's memory address. After I call print to see the values of the bank for each Employee and it is still printing values for each BankAccount
If I call delete shouldn't the memory on heap be delete and when print is called not output anything for BankAccount?
Here is the code:
vector<Employee*> employees;
//get employee full name & salary and return
employees.push_back(get_employee_info());
//setup their bank account
setup_bank(employees);
//make temp pointer to store bank memory address
BankAccount * tempBankPtr;
for (int i =0; i < employees.size(); i++) {
tempBankPtr =employees[i]->get_bank();
delete tempBankPtr // delete the heap object that pointer is pointing at
}
//print values
for (int i =0; i< employees.size(); i++) {
employees[i]->print();
}
code for print
void Employee:: print() const {
cout << "First name is: " << firstName << "\n";
cout << "Last name is: " << lastName << "\n";
BankAccount* bankholder = NULL;
bankholder = get_bank();
if(bankholder != NULL)
cout << "Account Balance is: " << get_bank()->get_amount() << "\n"; //prints values
}
getter for bank
BankAccount* Employee::get_bank() const{
return bank;
}
this is called in setup_bank
void Employee::set_bank(Employee* e, double amount){
bank = new BankAccount(amount);
}
If I call delete shouldn't the memory on heap be delete and when print is called not output anything for BankAccount?
No.
Deleting the object at that location in memory means it does not exist any more, so you're not allowed to access it.
It does not mean your program will magically print "nothingness" to protect you from this mistake.
Your program therefore has undefined behaviour; you must make sure you do not dereference an invalid pointer!
A very nice explanation of how free works.
When you call delete on the pointer and unlike as it has been suggested above you should only expect the following
Execute the destructor
The memory is not set to zero or any other magical value, since that is a very very expensive operation. When free is going to be called and if furthermore this will cause a call to sbrk is largely implementation dependent. The latter returns memory to the operating system.
For example AIX is well known to have a quite complex mechanism for memory management. What you should expect is that actually the block of memory will be marked as reallocatable , and new objects might overwrite your after the address pointed. Until this happens, you old staff are most probably still there.
Furthermore unlike stated before you can very well access it for as long as the data segment has not been reduced, and actually the object still exists , it is just that only you know about it.
That is why in this case you do not get SIGSEGV as you would expect. You probably get it later when you allocate something and the addressing a pointer in that memory area executes arbitrary code.
Accessing a delete pointer is undefined behavior and deleting it a second time is even more dangerous. To alleviate the situation there are many techniques , the most simple being encapsulation and deleting the pointer on the class destructor. You should set the pointer to nullptr.
Simplicity stops here, since you have to apply the rule of three (and a half ) . Thus it is better to work with shared or unique pointer provided by c++11 , and ignore these issues for now.
Related
My code snippet is as follows, however when I have 2 self defined classes and I define them, and print their memory address:
for(int i=0;i<2;i++){
Engine b;
Strategy d;
std::cout<<"be:"<<&b<<std::endl;
std::cout<<"elm:"<<&d<<std::endl;
}
it outputs:
be:0x7ffd92aee2c0
elm:0x7ffd92aede70
be:0x7ffd92aee2c0
elm:0x7ffd92aede70
i was expecting 2 different sets of memory addresses, but they are the same. Can someone tell me how to init into different address?
i was expecting 2 different sets of memory address
There is no reason to expect that. By the time the next iteration begins, the lifetime of the automatic object in the previous iteration has ended and so the object in the next iteration can reuse the same storage i.e. it can have the same memory address.
Can someone tell me how to init into different address?
You cannot specify the memory location where an object of automatic storage duration is allocated. But, if you create two objects whose lifetime overlaps, then they must necessarily be stored in separate addresses. john has shown how to do that using an array in his answer.
The obvious way is
Engine b[2];
Strategy d[2];
for(int i=0;i<2;i++){
std::cout<<"be:"<<&b[i]<<std::endl;
std::cout<<"elm:"<<&d[i]<<std::endl;
}
but the real question is why you care that the addresses are the same. Most likely its not something you need to worry about.
Both of the variables that you have outputted should only have 1 unique memory address, be, which is equal to
0x7ffd92aee2c0
was outputted twice, with no change to it whatsoever.
Then
elm:0x7ffd92aede70
was the same scenario, you outputted it twice with no change, what difference did you expect?
The code is working perfectly fine!
Objects created within block scope are created each time the block is entered and destroyed each time the block is left. In case of a loop, your objects b and d will be created and destroyed with each begin and end of an iteration, respectively. So you will get "new" objects with each iteration, but the compiler is free to use any address (even the ones used for the object of the prior iteration), so it may happen that you see the same addresses again and again. But it might also happen that you get different ones. Anyway, it makes no sense to rely on memory addresses of object which's life time has ended / will end, so the more interesting question is: "why do you care about memory addresses of e and d at all?".
To bring some light into that what happens try the following code. It shows how objects are created and destroyed in the course of your program:
class TestClass {
public:
TestClass (int x=0) : x (x) { cout << "Constructing " << x << endl; };
TestClass (const TestClass& t) : x (t.x) { cout << "CopyConstructing " << x << endl; };
TestClass (const TestClass&& t) : x (t.x) { cout << "Moving " << x << endl; };
~TestClass () { cout << "Destructing " << x << endl; };
int x;
};
int main() {
for(int i=0;i<2;i++){
TestClass b(i);
std::cout<<"elm:"<<&b<<std::endl;
}
}
Output:
Constructing 0
elm:0x7fff5fbff780
Destructing 0
Constructing 1
elm:0x7fff5fbff780
Destructing 1
I was given instructions to show that a pointer variable can contain a pointer to a valid object, deleted object, null, or a random value. Set four pointer variables a,b,c, and d to show these possibilities. The the thing im not sure about are the pointer objects. Can someone explain what I need to do to show case these pointers. or if I did it right.
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
class Pointer
{
public:
Pointer()
{
int num = 2;
}
Pointer(int num)
{
this->numb = num;
}
void set(int num)
{
numb = num;
}
int Get()
{
return numb;
}
private:
int numb;
};
int main ()
{
Pointer point;
Pointer* a;
a = &point;
Pointer*b = new Pointer(10);
delete b;
int* c = NULL;
srand(unsigned(time(0)));
int randNum = rand()%100;
int *d;
d = &randNum;
cout <<"Pointer a: " << a << endl;
cout <<"Pointer b: " << b << endl;
cout <<"Pointer c: " << c << endl;
cout <<"Pointer d: " << *d << endl;
//(*a) = (*b);
return 0;
}
Not a complete answer, because this is homework, but here’s a hint: once you generate random bits (The C++ STL way to do this is with <random> and perhaps <chrono>), you can store them in a uintptr_t, an unsigned integer the same size as a pointer, and convert those bits to a pointer with reinterpret_cast<void*>(random_bits). The results are undefined behavior. Trying to dereference the pointer might crash the program, or it might appear to work and corrupt some other memory location, or it might do different things on different runs of the program, but nothing you do with it is guaranteed to work predictably. This is Very Bad.
If “random” really means arbitrary, for this assignment, you could just declare a pointer off the stack (that is, inside a function and not static) and not initialize it. Ask your instructor if you aren’t sure.
That’s a very common source of irreproducible bugs, and I would recommend you get into the habit now of always initializing your pointer variables when you declare them. Often, that lets you declare them int * const, which is good practice, but even if you need to wait to assign a real value to them, if you initialize your pointers to NULL or nullptr, you will always see immediately in the debugger that the value is uninitialized, and you will always crash the program if you try to use it uninitialized.
I would like to first point out what the word NULL means or nullptr, which is what you should be using in C++11. The null pointer just assigns the pointer to an inaccessible address or location in the memory. This allows for safer code, because the "dangling pointers" left over could be bad.
A header file and another cpp file to define the class
Class Something{
// Class implementation here
};
Now lets go to the main.cpp file
#include "The header you made.hpp" // (.h or .hpp)
int main(int argc, char *argv[]){
Something objOne;
Something *objPointer = &objOne;
// Do stuff with objPointer
// Like use your member functions
Something *objPointerTwo = &objOne;
// Now objPointerTwo points to the same object
// Lets try some runtime allocation of memory
Something *objHeap = new Something();
// Do something with the pointer
// Watch this
delete objHeap;
objHeap = nulltpr;
// Now what happens when you try to access methods again with objHeap
// Your program will display a segmentation fault error
// Which means you are trying to mess with memory
// that the compiler does not want you too
}
All right so what is this memory? Well to put it simply you have the heap and the stack. All the stuff you put into your program is put into the stack when it is compiled. So when the program runs the code follows main and traces the stack kind of like a stack of boxes. You may get need to search through all the top ones to get to the bottom. Now what if a person didn't know for example how many students were going to be in the class that year. Well the program is already running how do you make more room? This is where the heap comes in. The new keyword allows you to allocate memory at runtime, and you can "point" to memory on the "heap" if you will. Now while this is all good and cool, it can be potentially dangerous which is why people consider C++ and C dangerous languages. When you are done using that memory on the heap you have to "delete" it so when the pointer moves, the memory does not get lost and cause problems. It is kind of like a sneaky ninja and it goes and causes trouble.
A good way to think about how pointers can be good for objects is if you create say a deck class, well how many cards does the user want we wont know until runtime, so lets have them type in the number, and we can allocate it on the heap! Look Below
int main(void){
int count;
Deck *deck = nullptr;
std::cout << "Enter amount of cards please:";
std::cin >> count;
deck = new Deck(count); // RUNTIME ALLOCATION ON HEAP!!!!
// This is so cool right, you can have a deck of any size
// Do stuff with deck
// Now that we are done with the deck don't forget to delete it
// We do not need all those cards on the heap anymore so....
delete deck; // Ahhh almost done
deck = nullptr; // Just in case since dangling pointers are weird
}
The key thing to understand here is, what is a pointer, what is it pointing to, and how do they work with the memory!
I am working on a small console game on my free time and have come across a bug I can't seem to fix no matter what I try. I have tried a lot of different things with the pointers so this is just the latest version of my code. I have been searching around and a few questions other's have asked indicated I may be experiencing a memory leak, or that I am reading values from beyond my arrays (don't understand how). However, those questions have been solved without leaving me any hints as to what is wrong with my code.
Basically, I have a function called int * spendAttribute(int point);
Since anything created in that function is out of scope in my main() I want to take 6 int out of that function, and bring them into my main().
I thought "hey why not use a pointer!" The function is supposed to return a pointer to an array created during the function, and paste it to another pointer created in main(), this has worked once before in my main(), but now it's not working and I have no clue why.
int * spendAttribute(int point)
{
string choice;
int hp,hpT,endur,endurT,dmg,dmgT,armor,armorT,agility,agilityT,evade,evadeT;
while(condition)
{
//do a bunch of junk ....
}
int stats[6] = {hp,endur,dmg,armor,agility,evade};
//some cout testing to see if values are correct (they are)
int* p_stats = new int [6]; //create a block of 6
p_stats = &stats[0]; //point to the first value of stats array
return p_stats; //return pointer
delete [] p_stats; //delete blocks
}
Note: I have tried without deleting the blocks and it still does not work. I tried this since I read that it might be a memory leak.I have tried it without using new at all.
main()
{
//.... some junk
while(main game loop)
{
int * pointer;
cout << "*************** Enter 'begin' to commence ****************** " << endl ;
cout << "*************** Enter 'spend' to use new attribute points ** " << endl ;
cin >> beginChoice; //declared before while loop
if(beginChoice == "spend")
{
cout << "total attributes: " << Bryan.returnAttribute() << endl ;
pointer = spendAttribute(Bryan.returnAttribute()); //copy pointer
cout << "TEST: " << endl ;
cout << pointer[0] << endl ; //out put is a bunch of random numbers..
cout << pointer[1] << endl ;
cout << pointer[2] << endl ;
cout << pointer[3] << endl ;
cout << pointer[4] << endl ;
cout << pointer[5] << endl ; //SOME DAMN BUG HERE
Bryan.addMaxHp(pointer[0]);
Bryan.addEndurance(pointer[0]);
Bryan.addDmg(pointer[0]);
Bryan.addArmor(pointer[0]);
Bryan.addAgility(pointer[0]);
Bryan.addEvasion(pointer[0]);
//after this character ends up having some ridiculous stats like -564553535%
//evasion or 9879967856 armor...
}
}
}
This method of transferring the array over to main worked for me before in this exact file, so I don't know exactly how I am getting these errors or what's causing them. I have even tried deleting the previous pointer used to see if thats what was causing it but it wasn't.
Please Halp.
Because you return a pointer to a local variable, and when that local variable goes out of scope you have a stray pointer.
And no, your allocation doesn't help, as you reassign the pointer to point to the local array, instead of copying into the allocated area. This of course means you also have a memory leak.
Regarding memory leak, you will still have a memory leak even when you fix the above problem. The reason being that you return from the function before you delete[] the pointer, and return returns from the function immediately, all code after a return statement is dead code. That means every time you call the function, it will allocate new memory which will never be free'd.
There are two obvious solutions to both the problems above: One is to allocate memory, copy the array into the allocated memory, and returning the pointer, and in the caller you do delete[] on the pointer.
The second solution is to pass in an array as argument, and use that instead of the local stats array.
p_stats is a pointer to int.
First you assign it to a newly allocated place in memory.
Then you move the pointer to point to local storage and return that. My guess is that you really wanted to return stats. Your options are:
Returns std::vector< int >. Probably simplest.
Modify your function to take a buffer to data and a length and fill it in.
Return std::array if available and you know it will be a fixed size of 6.
Although you could copy the data into p_stats then return that, it is not ideal because the calling function is then responsible to delete the data later.
If the fields have different meanings, you might want to create a struct with meaningful names for the values, and get your function to return that struct. e.g.
struct SpendAttribute // in header
{
int hp;
int endur;
int dmg;
int armor;
int agility:
int evade
};
SpendAttribute spendAttribute( int point )
{
SpendAttribute res;
// enter code here
return res;
}
There is a final option of putting the data into a smart-pointer like boost::shared_array<int> or you can use shared_ptr with an array-deleter.
For now, just return std::vector<int>
I am learning C++ from a game development standpoint coming from long time development in C# not related to gaming, but am having a fairly difficult time grasping the concept/use of pointers and de-referencing. I have read the two chapters in my current classes textbook literally 3 times and even googled some different pages relating to them, but it doesn't seem to be coming together all that well.
I think I get this part:
#include <iostream>
int main()
{
int myValue = 5;
int* myPointer = nullptr;
std::cout << "My value: " << myValue << std::endl; // Returns value of 5.
std::cout << "My Pointer: " << &myValue << std::endl; // Returns some hex address.
myPointer = &myValue; // This would set it to the address of memory.
*myPointer = 10; // Essentially sets myValue to 10.
std::cout << "My value: " << myValue << std::endl; // Returns value of 10.
std::cout << "My Pointer: " << &myValue << std::endl; // Returns same hex address.
}
I think what I'm not getting is, why? Why not just say myValue = 5, then myValue = 10? What is the purpose in going through the added layer for another variable or pointer? Any helpful input, real life uses or links to some reading that would help make sense of this would be GREATLY appreciated!
The purpose of pointers is something you will not fully realize until you actually need them for the first time. The example you provide is a situation where pointers are not needed, but can be used. It is really just to show how they work. A pointer is a way to remember where memory is without having to copy around everything it points to. Read this tutorial because it may give you a different view than the class book does:
http://www.cplusplus.com/doc/tutorial/pointers/
Example: If you have an array of game entities defined like this:
std::vector<Entity*> entities;
And you have a Camera class that can "track" a particular Entity:
class Camera
{
private:
Entity *mTarget; //Entity to track
public:
void setTarget(Entity *target) { mTarget = target; }
}
In this case, the only way for a Camera to refer to an Entity is by the use of pointers.
entities.push_back(new Entity());
Camera camera;
camera.setTarget(entities.front());
Now whenever the position of the Entity changes in your game world, the Camera will automatically have access to the latest position when it renders to the screen. If you had instead not used a pointer to the Entity and passed a copy, you would have an outdated position to render the Camera.
TL;DR: pointers are useful when multiple places need access to the same information
In your example they aren't doing much, like you said it's just showing how they can be used. One thing pointers are used for is to connect nodes like in a tree. If you have a node structure like so...
struct myNode
{
myNode *next;
int someData;
};
You can create several nodes and link each one to the previous myNode's next member. You can do this without pointers, but the neat thing with pointers is because they are all linked together, when you pass around the myNode list you only need to pass the first (root) node.
The cool thing about pointers is that if two pointers are referencing the same memory address, any changes to the memory address are recognized by everything referencing that memory address. So if you did:
int a = 5; // set a to 5
int *b = &a; // tell b to point to a
int *c = b; // tell c to point to b (which points to a)
*b = 3; // set the value at 'a' to 3
cout << c << endl; // this would print '3' because c points to the same place as b
This has some practical uses. Consider you have a list of nodes linked together. The data in each node defines some sort of task that needs to be done that will be handled by some function. As new tasks are added to the list, they get appended to the end. Since the function has a pointer to the node list, as tasks are added on it receives those as well. On the other hand, the function can also remove tasks as it completes them, which are then reflected back across any other pointers that are looking at the node list.
Pointers are also used for dynamic memory. Say you want the user to enter in a series of numbers, and they tell you how many numbers they want to use. You could define an array of 100 elements to allow for up to 100 numbers, or you could use dynamic memory.
int count = 0;
cout << "How many numbers do you want?\n> ";
cin >> count;
// Create a dynamic array with size 'count'
int *myArray = new int[count];
for(int i = 0; i < count; i++)
{
// Ask for numbers here
}
// Make sure to delete it afterwars
delete[] myArray;
If you pass an int by value, you will not be able to change the callers value. But if you pass a pointer to the int, you can change it. This is how C changed parameters. C++ can pass values by reference so this is less useful.
f(int i)
{
i= 10;
std::cout << "f value: " << i << std::endl;
}
f2(int *pi)
{
*pi = 10;
std::cout << "f2 value: " << pi << std::endl;
}
main()
{
i = 5
f(i)
std::cout << "main f value: " << i << std::endl;
f2(&i)
std::cout << "main f2 value: " << i << std::endl;
}
in main the first print should still be 5. The second one should be 10.
What is the purpose in going through the added layer for another variable or pointer?
There isn't one. It's a deliberately contrived example to show you how the mechanism works.
In reality, objects are often stored, or accessed from distant parts of your codebase, or allocated dynamically, or otherwise cannot be scope-bound. In any of these scenarios you may find yourself in need of indirectly referring to objects, and this is achieved using pointers and/or references (depending on your need).
For example some objects have no name. It can be an allocated memory or an address returned from a function or it can be an iterator.
In your simple example of course there is no need to declare the pointer. However in many cases as for example when you deal with C string functions you need to use pointers. A simple example
char s[] = "It is pointer?";
if ( char *p = std::strchr( s, '?' ) ) *p = '!';
We use pointers mainly when we need to allocate memory dynamically. For example,To implement some data structures like Linked lists,Trees etc.
From C# point of view pointer is quite same as Object reference in C# - it is just an address in memory there actual data is stored, and by dereferencing it you can manipulate with this data.
First of non-pointer data like int in your example is allocated on the stack. This means that then it goes out of the scope it's used memory will be set free. On the other hand data allocated with operator new will be placed in heap (just like then you create any Object in C#) resulting that this data will not be set free that you loose it's pointer. So using data in heap memory makes you do one of the following:
use garbage collector to remove data later (as done in C#)
manually free memory then you don't need it anymore (in C++ way
with operator delete).
Why is it needed?
There are basically three use-cases:
stack memory is fast but limited, so if you need to store big
amount of data you have to use heap
copying big data around is
expensive. Then you pass simple value between functions on the stack
it does copying. Then you pass pointer the only thing copied is just
it's address (just like in C#).
some objects in C++ might be
non-copyable, like threads for example, due to their nature.
Take the example where you have a pointer to a class.
struct A
{
int thing;
double other;
A() {
thing = 4;
other = 7.2;
}
};
Let's say we have a method which takes an 'A':
void otherMethod()
{
int num = 12;
A mine;
doMethod(num, mine);
std::cout << "doobie " << mine.thing;
}
void doMethod(int num, A foo)
{
for(int i = 0; i < num; ++i)
std::cout << "blargh " << foo.other;
foo.thing--;
}
When the doMethod is called, the A object is passed by value. This means a NEW A object is created (as a copy). The foo.thing-- line won't modify the mine object at all as they're two separate objects.
What you need to do is to pass in a pointer to the original object. When you pass in a pointer, then the foo.thing-- will modify the original object instead of creating a copy of the old object into a new one.
Pointers (or references) are vital for the use of dynamic polymorphism in C++. They are how you use a class hierarchy.
Shape * myShape = new Circle();
myShape->Draw(); // this draws a circle
// in fact there is likely no implementation for Shape::Draw
Attempts to use a derived class through a value (instead of pointer or reference) to a base class will often result in slicing and losing the derived data portion of the object.
It makes a lot more sense when you're passing the pointer to a function, see this example:
void setNumber(int *number, int value) {
*number = value;
}
int aNumber = 5;
setNumber(&aNumber, 10);
// aNumber is now 10
What we're doing here is setting the value of *number, this would not be possible without the use of pointers.
If you defined it like this instead:
void setNumber(int number, int value) {
number = value;
}
int aNumber = 5;
setNumber(aNumber, 10);
// aNumber is still 5 since you're only copying its value
It also gives better performance and you're not wasting as much memory when you're passing a reference to a larger object (such as a class) to a function, instead of passing the whole object.
Well to use pointers in programming is a pretty concept. And for dynamically allocating the memory it is essentiall to use pointers to store the adress of the first location of the memory which we have reserved and same is the case for releasing the memory, we need pointers. It's true as some one said in above answer that u cannot understand the use of poinetrs until u need it. One example is that u can make a variable size array using pointers and dynamic memoru allocation. And one thing important is that using pointers we can change the actual value of the location becaues we are accessing the location indirectly. More ever, when we need to pass our value by refernce there are times when references do not work so we need pointers.
And the code u have written is using dereference operator. As i have said that we access the loaction of memory indirectly by using pointers so it changes the actuall value of the location like reference objects that is why it is printing 10.
I have an extraction operator being used for a class that has a char* member 'name'. Here is my code from my main driver:
Player tempPlayer;
for(int i=0;i<4;i++){
fin >> tempPlayer;
}
I then go on to do something with that extracted player (which is irrelevant), but the issue is that each time the extraction operator is used, something strange occurs. Here is the definition of the operator:
ifstream& operator>>(ifstream& fin, Player& currentPlayer){
char* temp = new char[50];
char tempChar;
fin >> temp;
// importing from a file that contains names of about 6 characters each
stringCopy(currentPlayer.name, temp);
delete[] temp;
temp = NULL;
return fin;
}
stringCopy body:
void stringCopy(char *destPtr, const char *sourcePtr){
while(*sourcePtr!='\0'){
*destPtr = *sourcePtr;
destPtr++;
sourcePtr++;
}
*destPtr='\0';
}
I have been debugging by printing out the memory addresses being used for temp and the name.
The FIRST time the extraction operator is called, the player's name and the temp array have different memory addresses, which is what should happen. Then temp is then deleted and set to NULL, which I confirmed by printing the address (and getting '0'), and the address of the player's name remains after the function has returned.
However, on subsequent calls, the address of both temp AND the player's name become identical to the address of the first player's name. The name address SHOULD be the same, as it is the same object that is just being overwritten, but why is temp getting the SAME address as "name" if it is allocated with the new char[] keywords?
Here is some code I used when debugging:
Along each step of the way in the body of the operator:
cout << "temp address followed by name address: " << (void*)temp << " " << (void*)(currentPlayer.name) << endl;
In the main driver:
cout << "player " << i+1 << " has been extracted with name address " << (void*)(tempPlayer.name) << endl;
Here is the Player constructor:
Player::Player(){
name = new char[50];
stringCopy(name,"name");
ID = new int[5];
}
Excluding irrelevant data members, here is Player definition:
class Player{
public:
char* name;
};
When you delete[] something you've new[]ed, the standard library is allowed to reuse that memory. It's not surprising, therefore, that temp ends up getting the same address again and again. That is expected behavior and not a problem in and of itself.
The real problem is that in your "driver" code (a bit of code you haven't shown us), you have a shallow copy of tempPlayer somewhere. This copies the pointer to name, without allocating new storage. When that copy gets deleted, the destructor for Player deletes name in this shallow copy, releasing name to the heap.
Now the original is left pointing to freed memory. A future call to your operator>> then allocates this now supposedly-free memory. Oops!
Your short term fix was to remove the shallow copy. The long term, correct fix is to implement proper copy and copy-assignment constructors, as per the "Rule of 3" ( http://en.wikipedia.org/wiki/Rule_of_three_%28C++_programming%29 ), or if you want to be really C++11 friendly, the rule-of-5. (Same link.)
Alternately, you could consider making the copy and copy-assignment constructors private, which would prevent unwanted copies of these objects. (Some hints here: What's the most reliable way to prohibit a copy constructor in C++? )