Baffling error with an array of class pointers

S

Scotty

I'm a C++ novice and need help figuring out some odd behavior I've
encountered.

Here's the situation: I create a class and have its constructor store a
random number in a private "number" variable. The class also has a
"getNumber()" function that returns its stored number. A function in the
program creates five objects of this class and five pointers to these
objects, the latter of which are stored in a global array. When
"getNumber()" is called from the function that created these objects,
the correct number is returned. However, when called from a different
function, the returned number skyrockets! Here's an example from the
compiled program:

-Program output-
First display:
dummyArray[0]->getNumber(): 1
dummyArray[1]->getNumber(): 7
dummyArray[2]->getNumber(): 4
dummyArray[3]->getNumber(): 0
dummyArray[4]->getNumber(): 9

Second display:
dummyArray[0]->getNumber(): 4469728
dummyArray[1]->getNumber(): 4200022
dummyArray[2]->getNumber(): 2359128
dummyArray[3]->getNumber(): 4456499
dummyArray[4]->getNumber(): 2359104

An interesting fact is that when I omit the "dummyFunction2()" call in
the code below, I get a different result:

-Program output-
First display:
dummyArray[0]->getNumber(): 1
dummyArray[1]->getNumber(): 7
dummyArray[2]->getNumber(): 4
dummyArray[3]->getNumber(): 0
dummyArray[4]->getNumber(): 9

Second display:
dummyArray[0]->getNumber(): 1
dummyArray[1]->getNumber(): 7
dummyArray[2]->getNumber(): 4
dummyArray[3]->getNumber(): 4456499
dummyArray[4]->getNumber(): 2359104

Does anyone have an idea as to what's causing these strange occurrences?
Are there errors in my code? (See below!)

Here's the complete source code for the example program:

---CODE STARTS HERE---

#include <cstdlib>
#include <iostream>

using namespace std;

class Dummy{
public:
Dummy();
int getNumber();
private:
int number;
};

Dummy::Dummy(){
number=rand()%10;
}

int Dummy::getNumber(){
return number;
}

void dummyFunction1();
void dummyFunction2();
void dummyFunction3();
Dummy *dummyArray[5];

int main(){
dummyFunction1();
dummyFunction2();
dummyFunction3();
system("pause");
return 0;
}

void dummyFunction1(){
Dummy d1, d2, d3, d4, d5;
Dummy *d1Ptr=&d1, *d2Ptr=&d2, *d3Ptr=&d3, *d4Ptr=&d4, *d5Ptr=&d5;
dummyArray[0]=d1Ptr;
dummyArray[1]=d2Ptr;
dummyArray[2]=d3Ptr;
dummyArray[3]=d4Ptr;
dummyArray[4]=d5Ptr;

cout << "First display:\n";
cout << "dummyArray[0]->getNumber(): " << dummyArray[0]->getNumber()
<< "\n";
cout << "dummyArray[1]->getNumber(): " << dummyArray[1]->getNumber()
<< "\n";
cout << "dummyArray[2]->getNumber(): " << dummyArray[2]->getNumber()
<< "\n";
cout << "dummyArray[3]->getNumber(): " << dummyArray[3]->getNumber()
<< "\n";
cout << "dummyArray[4]->getNumber(): " << dummyArray[4]->getNumber()
<< "\n";
}

void dummyFunction2(){
cout << "\n";
}

void dummyFunction3(){
cout << "Second display:\n";
cout << "dummyArray[0]->getNumber(): " << dummyArray[0]->getNumber()
<< "\n";
cout << "dummyArray[1]->getNumber(): " << dummyArray[1]->getNumber()
<< "\n";
cout << "dummyArray[2]->getNumber(): " << dummyArray[2]->getNumber()
<< "\n";
cout << "dummyArray[3]->getNumber(): " << dummyArray[3]->getNumber()
<< "\n";
cout << "dummyArray[4]->getNumber(): " << dummyArray[4]->getNumber()
<< "\n\n";
}

---CODE ENDS HERE---

Thanks!
Scotty
 
O

Owen Jacobson

I'm a C++ novice and need help figuring out some odd behavior I've
encountered.

Here's the situation: I create a class and have its constructor store a
random number in a private "number" variable. The class also has a
"getNumber()" function that returns its stored number. A function in the
program creates five objects of this class and five pointers to these
objects, the latter of which are stored in a global array. When
"getNumber()" is called from the function that created these objects,
the correct number is returned. However, when called from a different
function, the returned number skyrockets! Here's an example from the
compiled program:

-Program output-
First display:
dummyArray[0]->getNumber(): 1
dummyArray[1]->getNumber(): 7
dummyArray[2]->getNumber(): 4
dummyArray[3]->getNumber(): 0
dummyArray[4]->getNumber(): 9

Second display:
dummyArray[0]->getNumber(): 4469728
dummyArray[1]->getNumber(): 4200022
dummyArray[2]->getNumber(): 2359128
dummyArray[3]->getNumber(): 4456499
dummyArray[4]->getNumber(): 2359104

Welcome to the wonderful world of undefined behaviour. More below.
Does anyone have an idea as to what's causing these strange occurrences?
Are there errors in my code? (See below!)

Here's the complete source code for the example program:

---CODE STARTS HERE---

#include <cstdlib>
#include <iostream>

using namespace std;

class Dummy{
public:
Dummy();
int getNumber();
private:
int number;

};

Dummy::Dummy(){
number=rand()%10;

}

int Dummy::getNumber(){
return number;

}

void dummyFunction1();
void dummyFunction2();
void dummyFunction3();
Dummy *dummyArray[5];

int main(){
dummyFunction1();
dummyFunction2();
dummyFunction3();
system("pause");
return 0;

}

void dummyFunction1(){
Dummy d1, d2, d3, d4, d5;
Dummy *d1Ptr=&d1, *d2Ptr=&d2, *d3Ptr=&d3, *d4Ptr=&d4, *d5Ptr=&d5;
dummyArray[0]=d1Ptr;
dummyArray[1]=d2Ptr;
dummyArray[2]=d3Ptr;
dummyArray[3]=d4Ptr;
dummyArray[4]=d5Ptr;

cout << "First display:\n";
cout << "dummyArray[0]->getNumber(): " << dummyArray[0]->getNumber()
<< "\n";
cout << "dummyArray[1]->getNumber(): " << dummyArray[1]->getNumber()
<< "\n";
cout << "dummyArray[2]->getNumber(): " << dummyArray[2]->getNumber()
<< "\n";
cout << "dummyArray[3]->getNumber(): " << dummyArray[3]->getNumber()
<< "\n";
cout << "dummyArray[4]->getNumber(): " << dummyArray[4]->getNumber()
<< "\n";

}

^^^ Right here, objects d1, d2, d3, d4, and d5 go out of scope and are
destructed. The pointers to those objects, stored in dummyArray, no
longer point to valid objects.
void dummyFunction3(){
cout << "Second display:\n";
cout << "dummyArray[0]->getNumber(): " << dummyArray[0]->getNumber()
<< "\n";

Here you dereference one of those pointers. The moment you do that
the behaviour of your program is not well-defined: for you it prints
completely arbitrary values, but it's allowed to do literally
anything. It could crash. It could work perfectly. It could email
your inlaws and invite them to stay with you for the next year. It
could cause cancer in rodents.

You have a couple of options for making dummyArray usable from both
functions:

1. Initialize the d?Ptr variables in dummyFunction1 with 'new'
instead of with pointers to objects on the stack. You are then
responsible for cleaning up those objects with 'delete' when you're
done with them.
2. Store the actual objects in the array rather than pointers to the
objects, by declaring it as Dummy dummyArray[5]; and performing no
initialization in dummyFunction1.
3. Create and populate the array in main(), and pass it to the
dummyFunction1 and dummyFunction3 functions as an argument.

Owen
 
J

Jack Klein

I'm a C++ novice and need help figuring out some odd behavior I've
encountered.

Here's the situation: I create a class and have its constructor store a
random number in a private "number" variable. The class also has a
"getNumber()" function that returns its stored number. A function in the
program creates five objects of this class and five pointers to these
objects, the latter of which are stored in a global array. When
"getNumber()" is called from the function that created these objects,
the correct number is returned. However, when called from a different
function, the returned number skyrockets! Here's an example from the
compiled program:

-Program output-
First display:
dummyArray[0]->getNumber(): 1
dummyArray[1]->getNumber(): 7
dummyArray[2]->getNumber(): 4
dummyArray[3]->getNumber(): 0
dummyArray[4]->getNumber(): 9

Second display:
dummyArray[0]->getNumber(): 4469728
dummyArray[1]->getNumber(): 4200022
dummyArray[2]->getNumber(): 2359128
dummyArray[3]->getNumber(): 4456499
dummyArray[4]->getNumber(): 2359104

An interesting fact is that when I omit the "dummyFunction2()" call in
the code below, I get a different result:

-Program output-
First display:
dummyArray[0]->getNumber(): 1
dummyArray[1]->getNumber(): 7
dummyArray[2]->getNumber(): 4
dummyArray[3]->getNumber(): 0
dummyArray[4]->getNumber(): 9

Second display:
dummyArray[0]->getNumber(): 1
dummyArray[1]->getNumber(): 7
dummyArray[2]->getNumber(): 4
dummyArray[3]->getNumber(): 4456499
dummyArray[4]->getNumber(): 2359104

Does anyone have an idea as to what's causing these strange occurrences?
Are there errors in my code? (See below!)

Here's the complete source code for the example program:

---CODE STARTS HERE---

#include <cstdlib>
#include <iostream>

using namespace std;

class Dummy{
public:
Dummy();
int getNumber();
private:
int number;
};

Dummy::Dummy(){
number=rand()%10;
}

int Dummy::getNumber(){
return number;
}

void dummyFunction1();
void dummyFunction2();
void dummyFunction3();
Dummy *dummyArray[5];

int main(){
dummyFunction1();
dummyFunction2();
dummyFunction3();
system("pause");
return 0;
}

void dummyFunction1(){
Dummy d1, d2, d3, d4, d5;

In the line above you define five dummy objects. Space is allocated
for them and their constructors executed. These are local objects in
this function, and have automatic storage duration. They live until
the function exits.
Dummy *d1Ptr=&d1, *d2Ptr=&d2, *d3Ptr=&d3, *d4Ptr=&d4, *d5Ptr=&d5;
dummyArray[0]=d1Ptr;
dummyArray[1]=d2Ptr;
dummyArray[2]=d3Ptr;
dummyArray[3]=d4Ptr;
dummyArray[4]=d5Ptr;

cout << "First display:\n";
cout << "dummyArray[0]->getNumber(): " << dummyArray[0]->getNumber()
<< "\n";
cout << "dummyArray[1]->getNumber(): " << dummyArray[1]->getNumber()
<< "\n";
cout << "dummyArray[2]->getNumber(): " << dummyArray[2]->getNumber()
<< "\n";
cout << "dummyArray[3]->getNumber(): " << dummyArray[3]->getNumber()
<< "\n";
cout << "dummyArray[4]->getNumber(): " << dummyArray[4]->getNumber()
<< "\n";

Here at the end of the function, the five dummy objects you created at
the beginning of the function go out of scope. The space the occupied
is released.
}

void dummyFunction2(){
cout << "\n";
}

void dummyFunction3(){
cout << "Second display:\n";
cout << "dummyArray[0]->getNumber(): " << dummyArray[0]->getNumber()
<< "\n";
cout << "dummyArray[1]->getNumber(): " << dummyArray[1]->getNumber()
<< "\n";
cout << "dummyArray[2]->getNumber(): " << dummyArray[2]->getNumber()
<< "\n";
cout << "dummyArray[3]->getNumber(): " << dummyArray[3]->getNumber()
<< "\n";
cout << "dummyArray[4]->getNumber(): " << dummyArray[4]->getNumber()
<< "\n\n";
}


When dummyFunction1() returns, dummyArray[] is left containing
pointers to objects that do not exist anymore. Attempting to
reference an object after its lifetime ends generates undefined
behavior. Printing some random numbers is one possible consequence of
undefined behavior.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
A

Andre Kostur

I'm a C++ novice and need help figuring out some odd behavior I've
encountered.

[snip description of objects appearing to change values]
Here's the complete source code for the example program:

---CODE STARTS HERE---

#include <cstdlib>
#include <iostream>

using namespace std;

class Dummy{
public:
Dummy();
int getNumber();
private:
int number;
};

Dummy::Dummy(){
number=rand()%10;
}

int Dummy::getNumber(){
return number;
}

void dummyFunction1();
void dummyFunction2();
void dummyFunction3();
Dummy *dummyArray[5];

int main(){
dummyFunction1();
dummyFunction2();
dummyFunction3();
system("pause");
return 0;
}

void dummyFunction1(){
Dummy d1, d2, d3, d4, d5;

OK, you create 5 local Dummy objects. These will go out of scope at the
end of this function.
Dummy *d1Ptr=&d1, *d2Ptr=&d2, *d3Ptr=&d3, *d4Ptr=&d4, *d5Ptr=&d5;

Now you take the addresses of all of those object. Minor alarm bells are
going off in my head. These are pointers to objects that will be
destroyed when this function ends. There's a potential for Undefined
Behaviour. Depends on what you do with these pointers.
dummyArray[0]=d1Ptr;
dummyArray[1]=d2Ptr;
dummyArray[2]=d3Ptr;
dummyArray[3]=d4Ptr;
dummyArray[4]=d5Ptr;

Now you're sticking those pointers into a global array. Really big alarm
bells are going off now. The potential of the program invoking Undefined
Behaviour just skyrocketed. Since these pointers are now in a global
array, other parts of the program are going to have access to them. And
if anybody attempts to dereference them after this function ends,
Undefined Behaviour.
cout << "First display:\n";
cout << "dummyArray[0]->getNumber(): " << dummyArray[0]->getNumber ()
<< "\n";
cout << "dummyArray[1]->getNumber(): " << dummyArray[1]->getNumber ()
<< "\n";
cout << "dummyArray[2]->getNumber(): " << dummyArray[2]->getNumber ()
<< "\n";
cout << "dummyArray[3]->getNumber(): " << dummyArray[3]->getNumber ()
<< "\n";
cout << "dummyArray[4]->getNumber(): " << dummyArray[4]->getNumber ()
<< "\n";

Those 5 dummy objects now go out of scope, and that global array still
contains the pointers to them. I'm almost certain that Undefined
Behaviour is going to happen sometime in the future.
}

void dummyFunction2(){
cout << "\n";
}

void dummyFunction3(){
cout << "Second display:\n";
cout << "dummyArray[0]->getNumber(): " << dummyArray[0]->getNumber ()
<< "\n";

And kaboom. It's not a potential Undefined Behaviour anymore. This code
has invoked Undefined Behaviour. The object that dummyArray[0] points to
no longer exists. (Same goes for the rest of the array)
cout << "dummyArray[1]->getNumber(): " << dummyArray[1]->getNumber ()
<< "\n";
cout << "dummyArray[2]->getNumber(): " << dummyArray[2]->getNumber ()
<< "\n";
cout << "dummyArray[3]->getNumber(): " << dummyArray[3]->getNumber ()
<< "\n";
cout << "dummyArray[4]->getNumber(): " << dummyArray[4]->getNumber ()
<< "\n\n";
}

---CODE ENDS HERE---

Thanks!
Scotty
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top