This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 years ago.
The printResults() method below (called from the main method at the bottom) returns -858993460 for all four values. Why is this? I have confirmed with cout statements that the numbers and calculations are correct within the doCalc() method, so I'm assuming the error is in the way I'm using pointers and calling the printResults() method...
typedef int matrix[2][2] ;
struct matrices {
matrix a;
matrix b;
};
...getInput() method constructs
matrix* doCalc (matrices m){
matrix toReturn;
char input;
cout << "Which calculation would you like to perform - (M)ultiply, (A)dd, (S)ubtract?";
cin >> input;
switch(input){
case 'M':
toReturn[0][0] = ((m.a[0][0])*(m.b[0][0]));
cout << "XX " << ((m.a[0][0])*(m.b[0][0]));
toReturn[0][1] = (m.a[0][1]*m.b[0][1]);
cout << "YY " << (m.a[0][1]*m.b[0][1]);
toReturn[1][0] = (m.a[1][0]*m.b[1][0]);
toReturn[1][1] = (m.a[1][1]*m.b[1][1]);
break;
case 'A':
toReturn[0][0] = (m.a[0][0]+m.b[0][0]);
toReturn[0][1] = (m.a[0][1]+m.b[0][1]);
toReturn[1][0] = (m.a[1][0]+m.b[1][0]);
toReturn[1][1] = (m.a[1][1]+m.b[1][1]);
break;
case 'S':
toReturn[0][0] = (m.a[0][0]-m.b[0][0]);
toReturn[0][1] = (m.a[0][1]-m.b[0][1]);
toReturn[1][0] = (m.a[1][0]-m.b[1][0]);
toReturn[1][1] = (m.a[1][1]-m.b[1][1]);
break;
}
return &toReturn;
}
void printResult(matrix m){
cout<<"---RESULT---\n";
cout << m[0][0] << " " << m[0][1] << "\n";
cout << m[1][0] << " " << m[1][1] << "\n";
}
void main() {
matrices m = getInput();
cout << m.a[0][0] << " " << m.a[0][1] << "\n";
cout << m.a[1][0] << " " << m.a[1][1] << "\n\n";
cout << m.b[0][0] << " " << m.b[0][1] << "\n";
cout << m.b[1][0] << " " << m.b[1][1] << "\n";
matrix* calc = doCalc(m);
matrix c = &calc;
printResult(*calc);
}
the matrix toReturn will be destroyed when the function exits, you will need to use some form of persistent memory allocation (look up new and delete). As such all the values are just nonsense.
matrix toReturn; is a local variable, allocated on the stack. After doCalc returns, its contents are undefined. In this case, the memory at its old address gets overwritten with random garbage.
toReturn will be destroyed with the stack frame when doCalc is finished.
Instead of returning the pointer pass it to the function you are calling.
void doCalc (matrices m, matrix* pReturnMatrix)
matrix* calc = new matrix();
doCalc(m, calc);
toReturn is a local variable in the doCalc function. It will no longer exist when the function returns.
An easy way to fix this is to pass a reference to the matrix that will store the result:
matrix* doCalc (matrices m, matrix& toReturn ){
Then remove this line from doCalc:
matrix toReturn;
And change how the function is called from this:
matrix* calc = doCalc(m);
matrix* calc = doCalc(m);
matrix c = &calc;
printResult(*calc);
To this:
matrix calc;
doCalc(m,calc);
printResult(calc);
There are other ways to fix this, e.g. new/delete as suggested in other places. However, now we will go into who allocates and who owns the memory. It won't be clear from the function signature alone who is responsible for what.
You can avoid managing dynamically allocated memory and requiring the caller supply an lvalue if you return by value.
matrix doCalc (const matrices& m)
{
matrix toReturn;
// Code here
return toReturn;
}
You can assign the results to a matrix object or use it in an expression like below.
if(doCalc(m).a[0][0] == 1)
{
// do something
}
or
matrix mat(doCalc(m));
if(mat.a[0][0] == 1)
{
// do something
}
Related
Before my program can free up memory and end it crashes. Crashes seem to happen on transition from the function UserDataCollection and back to main. This is only my second program using pointers so I'm still quite the newbie considering the whole point of c++ is to use pointers.
Here is the aforementioned code:
#include <iostream>
//Prototypes
void UserDataCollection(int * &movieData_ptr, int &numSurveyed); // Movie Statistics
void DisplayOutput(int *movieData_ptr, int numSurveyed); //Mean, Median, Mode (Display To Console)
//Global Constants
int main()
{
//Variables
int numSurveyed = 0;
//Pointers
int * movieData_ptr = nullptr;
movieData_ptr = new int[numSurveyed];
//"Program Start"
std::cout << "Program start...\n\n";
UserDataCollection(movieData_ptr, numSurveyed);
DisplayOutput(movieData_ptr, numSurveyed);
//Release Memory
delete[] movieData_ptr;
std::cout << "Memory Cleared.";
return 0;
}
void UserDataCollection(int * &movieData_ptr, int &numSurveyed)
{
//Get Number of Students Surveyed
std::cout << "How many students were surveyed: ";
std::cin >> numSurveyed;
//Student Data Input Loop
for (int i = 0; i < numSurveyed; i++)
{
//Get Student Data
std::cout << "Enter How many movies student " << i + 1 << " has seen in ONE month: ";
std::cin >> *(movieData_ptr + i);
//Validation Check
while (*(movieData_ptr + i) >= 337)
{
std::cout << "\nImpossible value!" << std::endl
<< "Hours in a month: 730. Average movie length: 130 minutes."
<< "Total Possible movies: 337";
std::cout << "\n\nEnter How many movies student " << i + 1 << " has seen in ONE month: ";
std::cin >> *(movieData_ptr + i);
} //end while (Validation Check)
} // end for (Data Input)
}
void DisplayOutput(int *movieData_ptr, int numSurveyed)
{
//Display loop for pointer array
for (int i = 0; i < numSurveyed; i++)
{
std::cout << *(movieData_ptr + i) << " ";
}
//End Message
std::cout << "\n\nProgram end.";
}
You never allocated any memory.
int numSurveyed = 0;
//Pointers
int * movieData_ptr = nullptr;
movieData_ptr = new int[numSurveyed];
This is the equivalent of
int *movieData_ptr = new int[0];
You are allocating size of 0 ints. This is undefined behaviour. You can't do anything useful with that pointer without a segmentation fault. You need to either pre-allocate a certain amount, and make sure you don't overflow, or dynamically allocate every time you plan to add data.
Since this is C++, it's probably better not to use raw pointers, but use vector or something instead.
Sorry:
From 5.3.4/7
When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.
From 3.7.3.1/2
The effect of dereferencing a pointer returned as a request for zero size is undefined.
I firstly intialize a hotel object and then initialize some room objects and print their id's respectively (which print out correctly.)
for(int j=0;j<5;j++){
Room r(1, 30);
hotel.addRoom(r);
cout << "Id: " << r.getId() << endl;
}
Then, I do this iteration on the list:
cout << "Initialized rooms with Ids: ";
for(auto iterator : hotel.getRooms()){
cout << iterator->getId() << " ";
}
cout << endl;
Also, here is the implementation on those methods, on the Hotel class:
//header
list<Room*> rooms;
//source
list<Room*> & Hotel::getRooms(){
return rooms;
}
And look at the output!
Every other part (like id generation and construction of objects) is tested and works fine.
Since you haven't posted a definition for the addRoom function, by the power of deduction I conclude it does something similar to:
void Hotel::addRoom(const Room& room) {
rooms.push_back(&room);
}
And then given the following loop:
for(int j=0;j<5;j++)
{
// This creates a Room object local to each iterator of the loop
Room r(1, 30);
// This adds the address of this local variable in the list
hotel.addRoom(r);
cout << "Id: " << r.getId() << endl;
// The variable r is destroyed here
}
So in the end your std::list<Room*> is filled with dangling pointers - pointers which point to memory which is no longer yours. This causes undefined behavior.
I recommend you drop the pointers altogether and change to:
class Hotel
{
std::list<Room> rooms;
public:
void addRoom(const Room& room) {
rooms.push_back(room);
}
std::list<Room>& Hotel::getRooms() {
return rooms;
}
const std::list<Room>& Hotel::getRooms() const {
return rooms;
}
};
I've tried debugging this in multiple ways. In my general assumption I think it may be a scoping issue with tempOperator. My assignment states that I need to have one example of passing by pointer, and within the section I used passing by pointer I can't also pass by address. I know for a fact the GetNumber function and the Printing function work perfectly. Something breaks with the pointer and I am not really sure what it is. The goal is to create a pointer to myOperator. Pass it into a function and change myOperator within that function.
#include <iostream>
#include <math.h>
#include <string>
using namespace std;
void GetNumber (float[], int); // prototype GetNumber function that accepts a float array data type.
char* GetOperator (char*); // prototype GetOperator to accept and return a copy of a poiunter.
void PrintProblem (float[], char, string&, float&); // Prototpe PrintProblem function to accept an array, character, string, and float address.
int main()
{
//------------------------------Declare Variables----------------
float storageBox [2]; // Declare an array contraing to floats.
float result; // Declare a float variable named result.
int functionCounter = 0; // Declare an integer variable named functionCounter and initialize it to 0.
char myOperator; // Declare a character variable data type and name is
string operatorType ; // Decare a string variable and name is operatorType.
char* pOperator = NULL;
//------------------------------Body-----------------------------
cout << "The address myOperator is: " << &myOperator << endl << endl; // View the Address of myOperator
GetNumber (storageBox, functionCounter); // Acquires a value and stores is in the array slot = functionCounter.
functionCounter += 1; // Make functionCounter equivalent to 1 more than it's previous value.
pOperator = &myOperator; // Make pOperator hold the Address of myOperator, and point to myOperator.
// ***********************************************************************
// Debugging Section - (Conclusion - myOperator isn't getting a memory location?)
// ***********************************************************************
cout << endl << "The address of pOperator is: " << &pOperator << endl; // View the Address of pOperator
cout << "The address myOperator is: " << &myOperator << endl << endl; // View the Address of myOperator
// ********************End Debug*****************************************
GetOperator (pOperator); // Make a call to the getOperator function and pass it a copy of the pointer pOperator.
// ***********************************************************************
// Debugging Section - (Something breaks)
// ***********************************************************************
cout << "The value stored in the location pOperator points to is : " << *pOperator << endl; // View the contents of pPointer.
cout << "The value of myOperator is: " << "\n\n" << myOperator; // View the contents of myOperator.
// ********************End Debug*****************************************
GetNumber (storageBox, functionCounter); // Acquires a value and stores is in the array slot = functionCounter.
PrintProblem(storageBox, myOperator, operatorType, result); // Prints the outcome
return 0;
}
// First Function - pass by refference (will grab a single Number)
void GetNumber (float storageBox[], int functionCounter) //(Functioning properly)
{
float tempNumber;
cout << "Enter a number : ";
cin >> tempNumber;
storageBox[functionCounter] = tempNumber; // fills the array slot functionCounter represents with tempNumber
}
// pass by pointer to obtain the operator and problem type.
char* GetOperator (char* pOperator)
{
char tempOperator;
cout << "Please enter a mathematical operator ( +, -, *, /): ";
cin >> tempOperator;
pOperator = &tempOperator; // set the copy of pOperator to the adress of tempOperator
// ***********************************************************************
// Debugging Sectopn- (Functional)
// ***********************************************************************
cout << "\nThe value found in pOperator is : " << *pOperator << endl; // output the contect of the memory location pOperator points to.(tempOpertor)
// ********************End Debug*****************************************
return (pOperator);
}
// Everything beyond this point functions properly.
// pass by copy on output
void PrintProblem (float storageBox[2], char myOperator, string& operatorType,
float& result)
{
switch (myOperator)
{
case '+':
{
operatorType = "Addition: ";
result = storageBox[0] + storageBox[1];
break;
}
case '-':
{
operatorType = "Subtraction: ";
result = storageBox[0] - storageBox[1];
break;
}
case '*':
{
operatorType = "Multiplication: ";
result = storageBox[0] * storageBox[1];;
break;
}
case '/':
{
operatorType = "Division: ";
result = storageBox[0] / storageBox[1];
break;
}
default:
{
cout << "\nYour operator is invalid!\n\n";
}
}
cout << operatorType << storageBox[0] << " " << myOperator << " "
<< storageBox[1] << " " << " = " << result;
}
GetOperator is "reversed" – you shouldn't assign the address of the local variable to the parameter, you should assign the value of the local variable to the variable that the parameter points to:
*pOperator = tempOperator;
Why is your GetOperator function declared to return a char*?
Currently your GetOperator function is assigning the address of a local parameter to the pOperator function parameter. You probably want to assign the local parameter to the thing pointed-to by pOperator - that is, where you have this line:
pOperator = &tempOperator;
You probably want:
*pOperator = tempOperator;
EDIT:
Here's a somewhat simpler example of what's going on:
#include <iostream>
void SetValueNotWorking(int* i) {
int bar = 42;
// Sets the function parameter 'i' to the address of 'bar'
i = &bar;
}
void SetValueWorking(int* i) {
int bar = 42;
// Sets the int pointed-to by function parameter 'i' to the value of 'bar'
*i = bar;
}
int main(int argc, char** argv) {
int foo = 0;
SetValueNotWorking(&foo);
std::cout << foo;
SetValueWorking(&foo);
std::cout << foo;
return 0;
}
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
I'm trying to learn C++ and had a question about returning arrays in C++. I know that in this case perhaps Vector may be better and that there is no need for a getter method as the fields are visible within the same class but I'm trying to learn about memory management so I'll use them.
class Color {
double r;
double g;
double b;
public:
Color(int a, int aa, int aaa) {
r = a;
g = aa;
b = aaa;
}
bool operator==(const Color &other) {
double *otherCol = other.getter();
return otherCol[0] == r && otherCol[1] == g && otherCol[2] == b;
}
double* getter() const {
double second[3] = {r,g,b};
return second;
}
};
int main() {
Color col1(23, 54, 200);
Color col2(23, 54, 200);
cout << (col1 == col2) << endl;
return 0;
}
This code should print out a 1 if the RGB colors are the same and 0 otherwise. But it does not print a 1. To debug, I added the following lines (twice on purpose) right before the return statement in operator==:
cout << otherCol[0] << " " << otherCol[1] << " " << otherCol[2] << endl;
cout << otherCol[0] << " " << otherCol[1] << " " << otherCol[2] << endl;
Oddly enough, the results are different:
23 54 200
6.91368e-310 6.91368e-310 3.11046e-317
Can someone please tell me what causes this and what would be a reasonable remedy that does not rely on Vector or dynamic allocation of memory? Let's assume that we don't want to pass in an array into getter() to update.
In getter you are returning the address of a local variable which results in undefined behavior so you are getting random memory. If you return a pointer you have to do something like new the variable in the called function and delete it after the function returns.
Or you could make second a class member which would keep it from going out of scope.
You could also pass the array in as a parameter.
I have created my own Vector and Array classes which I have tested and work fine. However, in the following code I am having problems accessing the methods in an AccountInfo class.
_accounts is declared like this:
Vector<AccountInfo*> _accounts[200]; // store up to 200 accounts
Before, _accounts was only of type AccountInfo. After switching to a vector, every instance that uses _accounts has the error: Expression must have pointer type.
Here is my code:
ostream& operator << (ostream& s, UserDB& A){
// print users
for (unsigned int i = 0; i < A._size; i++){
//print name
s << A._accounts[i]->getName() << endl;
}
return s; // return the statement
}
//---------------------------------------------------------------------------- --------------------
//Destructor of UserDB
UserDB::~UserDB(){
for (int i = 0; i < _size; i++){
delete[] _accounts[i]; // delete objects in _accounts
}
}
//------------------------------------------------------------------------------------------------
// add a new user to _accounts
void UserDB::adduser(AccountInfo* newUser){
_accounts[_size] = newUser;
_size++; //increment _size.
if (newUser->getUID() > 0){
//print if UID has a value
cout << newUser->getName() << " with " << newUser->getUID() << " is added." << endl;
}
else {
newUser->setUID(_nextUid); //automatically set UID for user if empty
cout << newUser->getName() << " with " << newUser->getUID() << " is added." << endl;
_nextUid++;
}
}
Is there a way to access the AccountInfo methods from the variable _accounts?
You defined an array of vectors with:
Vector<AccountInfo*> _accounts[200]; // store up to 200 accounts
This is not the same as declaring a single vector with a capcity of 200. If you were using a standard vector then it would look like:
std::vector<AccountInfo*> _accounts(200); // store up to 200 accounts