"The value is never used" pointer re-assignment C++ - c++

I'm refactoring this bit of code:
struct GameState {
PieceState piece;
}
//create local copy from piece, modify it, and only when its VALID copy it back!
void update_game_play(GameState *game, const InputState *input) {
PieceState piece = game->piece;
//'left' from perspective of the game
if (input->dleft > 0) {
--piece.offset_col;
}
if (is_piece_valid(&piece, game->board, WIDTH, HEIGHT)) {
game->piece = piece;
}
}
This code takes a piece struct, and only when it's valid it's re-assigned to the GameState struct.
But in my refactored code the assignment gives me a warning that the value is never used in the last line, inside the if-statement:
//create local copy from piece, modify it, and only when its VALID copy it back!
void update(Piece *pieceTmp, Board *board) override
{
auto piece = *pieceTmp;
//'left' from perspective of the game
if (input.dleft > 0) {
--piece.offset_col;
}
//test with dummy if statement
if (true) {
pieceTmp = &piece; //"the value is never used"
}
}
The way I understood it, is that I'm dereferencing the pointer to a object, changing the object properties, and then assign the address of the object to my original pointer? What's going on?

The function accepts the first argument by value.
void update(Piece *pieceTmp, Board *board) override
That is it deals with a copy of the value of the original argument.
So the new value of the pointer
pieceTmp = &piece;
is used nowhere in the function (and in the caller).
Another problem is that you are trying to assign the address of a local variable that will not be alive after exiting the function. So after exiting the function the pointer (if it will be passed by reference) will have an invalid value.
Instead of this statement
pieceTmp = &piece;
you could write for example
*pieceTmp = piece;

Related

pointer returned to an object turns null after function returns address

I am new to CPP and I am writing a program as an assignment to simulate a train path system that includes destinations and starts using object oriented programming .
I have 2 classes as shown below (there is a a passenger class but it is not relevant ) :
class Train
{
public:
int cooldown_time;
int travel_time;
int time_since_movement;
int id;
class Station *start;
class Station *destination;
vector<Passenger *> current_passengers;
string status;
void add_train(vector<string> commands, vector<Station> stations, vector<Train> &trains)
{
travel_time = stoi(commands[THIRD_PART + 1]);
cooldown_time = stoi(commands[THIRD_PART + 2]);
status = TSTATUS1;
start = station_search(stations, commands[SECOND_PART]); // this is where the problem happens
destination = station_search(stations, commands[THIRD_PART]);
id = stations.size();
}
};
class Station
{
public:
int tuffy_price;
string city_name;
vector<Passenger *> current_passengers;
vector<Train *> current_trains;
int id;
void add_station(vector<Station> &stations, vector<string> &commands)
{
tuffy_price = stoi(commands[THIRD_PART]);
city_name = commands[SECOND_PART];
id = stations.size();
}
};
I have a search function dedicated to finding the start and destination based off a command that user enters for example :the user enters "add_train cityname1 cityname2 <cooldown_time> <travel_time>". my program detects the city names and searches a vector I have named stations with a key that is the city name and returns a pointer (because of the complications in memory behavior in a function , i set it to pointer) to that station-object .
the function is as below :
Station *station_search(vector<Station> stations, string key)
{
Station *dummy;
for (int i = 0; i < stations.size(); i++)
{
if (stations[i].city_name == key)
{
return &stations[i];
}
}
return dummy;
}}
my problem is with my search function's weird behavior , when I debug the program I see the function find the correct station object and return a pointer to it ,but when the execution returns to the constructor function it randomly (maybe not randomly ) turns the first pointer relating to the start station to null and replaces the values inside with garbage ones.
but after the function searches for the destination station it does not do this and the execution is correct.
Could someone explain why this error is occurring?
My guess is that I have not understood local variables and pointer returns well enough and I have committed a rookie mistake somewhere but I don't seem to find it .
PS: I did not include the full code as it's too long I can include it by attaching a file ,comment down if it's necessary.
Station *station_search(vector<Station> stations, string key)
If you take a closer look here, you will see that the stations parameter is passed by value, which means that after this function returns, this stations parameters will get destroyed. It will be no more. It will cease to exist. It will become an ex-parameter.
However this station_search returns a pointer to some value in this vector. Therefore, rules of logic dictate that it will return a pointer to a destroyed object. Attempting to dereference that pointer, in any way, becomes undefined behavior.
Your other class methods receive parameters by reference, so you must already understand the difference between passing parameters by value vs. by reference, so you should simply do the same here.
Here you are passing a copy of the vector, which is destroyed when the function returns. Additionally, if the key is not found an uninitialized pointer is returned.
Station *station_search(vector<Station> stations, string key)
{
for (Station &station : stations)
{
if (stations.city_name == key)
{
// Pointer becomes invalid when you leave.
// Accessing this pointer will cause undefined behavior.
return &station;
}
}
// This would always cause undefined behavior as dummy was not initialized.
return nullptr;
}
You should pass in a reference and initialize dummy:
Station *station_search(vector<Station> &stations, string key)

Basic C++ segfault when using new and passing a pointer

Can somebody please explain the segfault here:
class foo
{
private:
some_class *test_;
void init_some_class(some_class*);
void use_class();
}
foo::foo()
{
//test_ = new some_class(variables, variables); //THIS WOULD WORK
}
void foo::init_some_class(some_class *tmp)
{
tmp = new some_class(variables,variables);
}
void foo::use_class()
{
test_->class_function() //THIS SEGfaults
}
I would call the funtion via init_some_class(test_); If I use new in the constructor then the test_->class_function() works fine. It only seems to segfault when I use new outside of the class constructor and try and pass the pointer through the function
When you write in init_some class() :
tmp = new some_class(variables,variables);
you are in fact storing the new pointer in the parameter that is passed by value. But this parameter is local to the function and lost as soon as the function returns.
So if you call somewhere init_some class(test_) the value of test_ is transferred to tmp, but the changed tmp remains local to the function. You therefore get a segfault beause test_ remains uninitialized.
Possible solutions:
A simple solution to the described use case could be to pass the parameter by reference:
void foo::init_some_class(some_class *& tmp) // note the &
{
tmp = new some_class(variables,variables);
}
With this definition, when calling init_some class(test_), the original test_ pointer gets modified.
Another solution could be to have the init_some_class() change directly the test_ member. You'd then no longer need a parameter.

C++ Empty Pointer

So I am new to C++ and I am trying to use an inner class like this:
struct PreviousButton {
SelectionScreen* ss;
PreviousButton(SelectionScreen* sss) {
ss = sss;
}
void ClickAction() {
//images is a vector with images. in here it is empty
ss->images;
}
};
This inner class is inside the class SelectionScreen and I need to perform a click action and need some of the variables of the selectionscreen.
SelectionScreen:
class SelectionScreen {
public:
void AddImage(Image img);
std::vector<Image> images;
How I fill the vector:
Image* image = new Image{ };
AddImage(*image2);
AddImage method:
void SelectionScreen::AddImage(Image img)
{
images.push_back(img);
}
But when I try to use the selectionscreen inside the class all of the variables are empty. But when I look into selectionscreen all of the variables are set.
The way I pass the SelectionScreen:
PreviousButton* previousButton = new PreviousButton(*ren, this);
How SelectionScreen gets initialized: (this method is called from the main)
int Program::Render() {
bool quit = false;
MenuScreen m = SelectionScreen{ Sdl_Renderer };
// change current screen to selectionscreen
ScreenController::GetInstance().ChangeMenu(m);
while (!quit) {
// handle user input and repaint
}
// delete all windows if quit is true
SDL_DestroyRenderer(Sdl_Renderer);
SDL_DestroyWindow(Sdl_Window);
SDL_Quit();
return 0;
}
Does anyone knows why my variables are empty?
This isn't addressing the immediate issue you describe, but you have a serious problem here:
ss->currentImageIndex = ss->images.capacity() - 1;
images.capacity() - 1 is not guaranteed to return a valid index into your vector. You should use images.size() - 1.
std::vector::capacity() tells you the storage space currently allocated for the vector, not the number of elements it actually contains.
UPDATE
When you assign a SelectionScreen to a MenuScreen like this
MenuScreen m = SelectionScreen{ Sdl_Renderer };
you "slice" the SelectionScreen object (see What is object slicing?).
This line creates a new MenuScreen object, m, by copy-constructing it from a temporary SelectionScreen object. The new MenuScreen object, m, is not a SelectionScreen. It is also a completely distinct object from the temporary SelectionScreen created on the right-hand side of this expression.
Your PreviousButton, which I assume is created in the constructor of SelectionScreen, holds a pointer to the temporary SelectionScreen, which the compiler is free to delete once this line has completed.
To fix this, you could use this initialisation instead:
MenuScreen& m = SelectionScreen{ Sdl_Renderer };
In this case, m is a reference to your (temporary) SelectionScreen - this is good because (a) references are polymorphic, so it still knows that it's really a SelectionScreen, not just a MenuScreen and (b) it's a reference to the exact same SelectionScreen object created on the right-hand side, which your PreviousButton has a pointer to. I've also bracketed the "temporary" bit now, because taking a local reference to a temporary guarantees it will exist for as long as the reference does (see e.g. Does a const reference prolong the life of a temporary?).
Note that I am assuming here that you only make use of this SelectionScreen within the while (!quit) loop that follows, i.e. the screen can safely be deleted at the end of this int Program::Render() method.

C++ MFC - CMapPtrToPtr - SetAt and Lookup

I'm using MFC C++ for my Windows Application, where I need to persist (not in a Database) some data using CMapPtrToPtr. The key is a pointer to a structure (let's call it SIGNAL_DATA* pSignal) and the value is a double array.
The problem is, when I read the value again, it is giving me a garbage/undefined value (not the value I stored).
Sample Code:
In the header file:
CMapPtrToPtr prevZoomValsMap;
double zoomPreVals[2];
In the implementation class:
void funktion1()
{
if(ersteSchleife == FALSE) //first time, it is false
{
SIGNAL_DATA* pSelectedSignal; //properly initialised. verified in debug mode
zoomPreVals[0] = zoomMinSkal; //valid double values. verified in debug mode
zoomPreVals[1] = zoomMaxSkal;
prevZoomVals.SetAt((void*) pSelectedSignal, (void*) zoomPreVals);
ersteSchleife = TRUE;
}
else
{
funktion2();
}
}
In another function, when I read the value as below, I'm getting garbage values.
void funktion2()
{
void *zoomValuesTemp_;
prevZoomValsMap.Lookup((void*) sigTemp, zoomValuesTemp_);
double *zoomValuesTemp = (double*)zoomValuesTemp_;
if(zoomValuesTemp == NULL) //verified in debug mode. never becomes NULL.
{
int aRTD = 10; //dummy assignment.
}
double aValue = zoomValuesTemp[0] ; //Access Violation
}
Assuming that the code you provide is running in a function, we get
void store_it(SIGNAL_DATA* pSelectedSignal)
{
double zoomPreVals[2] = {zoomMinSkal, zoomMaxSkal}; //also, initialised.
prevZoomVals.SetAt((void*) pSelectedSignal, (void*) zoomPreVals);
}
If this is what you have, then you are storing the address of a local variable (zoomPreVals) in the map. Since zoomPreVals is destroyed at the end of the function, the pointer to zoomPreVals becomes invalid. You cannot use this pointer anymore.
You must make sure that the pointer stays valid, so you can for example allocate a new structure with new and store the pointer in the map - don't forget to free the data later.
You might also consider using CMap<SIGNAL_DATA*, SIGNAL_DATA*, MYDATA, MYDATA&> and store objects instead of pointers as map values.
You might also consider using STL classes like map and unique_ptr.
Your retrieval code is not correct. You should not cast to match the function parameters, but pass the right parameters.
void *zoomValuesTemp_;
prevZoomVals.Lookup((void*) sigTemp, zoomValuesTemp_);
double *zoomValuesTemp = (double*)zoomValuesTemp_;

Reading new, filled array gives segfault

I've been banging my head hard over this...I create a pointer in main(), which I pass on to another function. Inside that function, the pointer is used to create a new array (using the new operator), the array is filled, and the function ends.
If I then try to access elements in the new array in the caller, I get a segfault. Since the new operator was used, I expect the new array to be on the heap and thus not cleared by it going out of scope...I really don't get this. What am I overlooking? I also don't know precisely what to google for, so no luck there yet.
I can get it to work if I let the function return the pointer (instead of passing it), but I don't want to do that because eventually I'd like my function to create a few such newly created arrays. So what am I missing here?
Here is a minimal working example:
#include <iostream>
#include <stdio.h>
bool getData(double *myData)
{
myData = new double[2];
if (!myData)
return false;
myData[0] = +4.53;
myData[1] = -3.25;
return true;
}
int main()
{
double *myData = NULL;
if (!getData(myData))
fprintf(stderr, "Could not get data.\n");
std::cout << myData[0] << std::endl;
std::cout << myData[1] << std::endl;
delete [] myData;
}
Root Cause of the Crash:
When you pass a pointer to the function by value. An copy of the pointer gets passed to the function. Further You allocate memory to the copy of pointer passed through main, this pointer is not same as the one you access in main, it is an copy. The pointer myData in main was never allocated any memory, so eventually you are dereferencing a NULL pointer which results in a Undefined Behavior and an crash.
Suggested Solution 1:
Pass the pointer by Reference:
bool getData(double *&myData)
^
And you are good to go.This is the C++ way of doing it.
Another Solution:
You could also do:
bool getData(double **myData)
^
{
*myData = new double[2];
//so on
}
while calling it as:
getData(&myData);
^
A word of caution:
new does not return NULL in case of failure to allocate memory. It throws a std::bad_alloc exception. So you need to handle that exception or in case you want to check for null you should use the nothrow version of new.
The pointer argument to getData() is passed by value, not by reference. This means you're pushing the value (== the address the pointer points to) on the stack and call getData. Inside getData you overwrite this value with the return value from new[]. This value is no longer valid after returning from the function as it only existed on the stack.
Try to pass a reference or pointer to the pointer:
bool getData(double *&myData)
{
myData = new double[2];
if (!myData)
return false;
myData[0] = +4.53;
myData[1] = -3.25;
return true;
}
You have to pass a double** as myData, to initialize correctly your array. Currently, your getData function creates an array and stores its value in the copied parameter, so myData in main is not modified. Your must pass the pointer of myData and modify it with
bool getData(double** myData)
{
*pmyData = new double[2];
...
}
and call getData in main:
getData(&myData);
The myData given as parameter to getData function is passed on stack as a copy. When modifying that value in getData function you actually modify the value from the stack.
When you return to the main function everything is as it was before (except a memory leak).
The quickest solution would be to change the getData function like this:
bool getData(double *&myData)
and you're all set.
You pass the pointer into your function by value, not reference. Try this:
bool getData(double* &myData)
{
...
}
The difference is that myData is now a reference to the pointer in main, not a copy of it that gets destroyed when the function exits.