Why does pass by reference cause this to crash (C++)? - c++

I'm experiencing some weird behavior and I'm not really sure where to turn.
Basically, I have a set of classes and one of them should be constructed with instances of the other two. I'm using pass by reference to assign the resources but the second assignment is crashing on my machine. I don't understand why the second assignment crashes but the first works fine. To make this a little more confusing, I tried recreating the problem in an online cpp compiler, but it seems to run fine in that environment.
I obscured the class names and removed a few methods that didn't seem relevant to this problem. Does anyone have any ideas?
#include <iostream>
using namespace std;
class Driver{};
class ITransmission{};
class ManualTransmission : public ITransmission {};
class Car
{
public:
Car(ITransmission &trans, Driver &driver);
private:
ITransmission *m_trans;
Driver *m_driver;
};
Car::Car(ITransmission &trans, Driver &driver)
{
*m_trans = trans;
*m_driver = driver; // <-- **** Crashes here!?!? ****
}
int main()
{
ITransmission *trans = new ManualTransmission();
Driver *driver = new Driver();
Car car(*trans, *driver);
return 0;
}

*m_trans and *m_drivers are only pointers to their respective types. They are not the object themselves. In your copy constructor you are calling
*m_trans = trans
which crashes because m_trans doesn't point to anything and you are dereferencing it.
What you want instead is,
m_trans = &trans
m_driver = &driver
This sets the pointer to point at the address of the object you've passed in, whereas before you were trying to assign to the pointed-to object.

Related

Linking pointers to pointers between classes (communicating classes)

I've tried to solve my problem for 2 days now and failed miserably. Internet does not help.
What I'm trying to do is to communicate two classes which reside within another class.
This is my first "big" project so I assume my design is terrible for you guys.
Also, my program is split between a lot of files which may be confusing.
Lets hit it! For the sake readability, I've changed every member to public.
This is my MainOGLController class which is the main class that controls everything my program does:
class MainOGLController
{ // I deleted constructor/destructor from this quote
public:
DisplayController* Display;
StellarManager* Manager; // it will need to use something from Display
void RenderScene();
bool CreateNewDisplay(int, char*[]); // argc argv
}
Ok, this is how i create instance of this class in file with main():
#include "MainOGLController.h"
MainOGLController Controller;
int main(int argc, char* argv[])
{
if ( Controller.CreateNewDisplay(argc, argv) ) return 1; // if it fails then exit;
// some opengl code here
return 0;
}
Now you are probably wondering how does the CreateNewDisplay method look like:
bool MainOGLController::CreateNewDisplay(int argc, char* argv[])
{
Display = new DisplayController(argc, argv);
Manager = new StellarManager(&Display); // me trying to make reference to Display
// to be able to use it within Manager
//ogl code
else return 0;
}
OK, so I'm creating Manager there and now we should see how i created the StellarManager class:
class StellarManager
{
std::vector<Stellar*> VectorManager; // objects from this vector will need to use
// ptrDisplay to access Display
DisplayController* ptrDisplay;
StellarManager(DisplayController&);
void addEntity();
};
Now for the constructor:
StellarManager::StellarManager(DisplayController& _p) // me trying to do anything
{
*ptrDisplay = _p;
}
So at this point I should have instance of MainOGLController, and within it, a pointer to DisplayController and StellarController, where StellarController should have its own pointer to the same DisplayController.
Now somewhere withing working piece of code I'm calling the addEntity method:
void StellarManager::addEntity()
{
VectorManager.push_back(new Stellar(&ptrDisplay); // sending ptrDisplay so that the
// Stellar object can use it
}
Stellar class is defined like this:
class Stellar
{
public:
DisplayController* ptrDisplay;
Stellar(DisplayController**);
void Draw(); // finally, heres where i want to use this Display pointer
};
Stellar constructor:
Stellar::Stellar(DisplayController** _p)
{
*ptrDisplay = **_p;
}
OKAY! Thats the final piece. All i want to do now is simply call method Draw which belongs to Stellar class and use Display which is located in MainOGLController.
Manager->VectorManager[0].Draw();
Oh and the Draw looks just like this:
void Stellar::Draw(int _mode)
{
GLMatrixStack* mvm = &(ptrDisplay->modelViewMatrix);
mvm->Scale(2, 0.5, 0.5); // Scale is a method from GLMatrixStack
}
Thats all folks, if theres any better way of doing this, im all ears.
What I did does not work, I'm able to use the *ptrDisplay from Stellar class but nothing happens so I guess I'm not using its reference but a copy.
Sorry, I know this is a lot of code and it may be very confusing. I just dont know what to do now...
It looks like the problem is here:
Stellar::Stellar(DisplayController** _p)
{
*ptrDisplay = **_p;
}
You're dereferencing a pointer (ptrDisplay) that was never initialized. This results in undefined behavior. I think this captures what you wanted to do:
Stellar::Stellar(DisplayController* _p) : ptrDisplay(_p)
{
}
It's not necessary to pass a pointer-to-pointer-to-DisplayController; all your Stellar class needs is a pointer to a DisplayController. Moreover, it sounds like you don't want to dereference _p and copy it, so simply copying the pointer (via ptrDisplay(_p)) will result in ptrDisplay pointing to the same object as _p.

How to initialize a static member object?

I didn't know that I didn't know this :) . and a similar question here didn't help much.
So here i am asking. Please Consider the following class:
//in Agent.h
class Agent : public ns3::Object{
private:
//...
static BaseWifi m_wifi;
//...
};
is this :
//Agent.cpp
BaseWifi temp;
BaseWifi Agent::m_wifi = temp;
very much different from this:
//Agent.cpp
BaseWifi Agent::m_wifi = BaseWifi();
The second approach doesn't work for me.
why and how?
I don't want to trouble you with more codes coz I faced this problem deep in my program. The program generate seg faults as things(members) inside BaseWifi's constructor are not initialized correctly. when those uninitialized internal members are used, seg faults occur.
Thank you in advance for your kind comments and answers.
p.s.:
In fact I found this issue when I hadn't yet initialized this static member and I was deleting an extra line :
BaseWifi temp;
in my main(), which added more to my confusion!!!(this one could be dependent on what I put in BaseWifi's constructor, so dont mind it for now)
Update-1:
For those who would like to see the BaseWifi:
class BaseWifi {
ns3::WifiHelper m_wifiHelper; // a wifi helper apply to setup vehicles Wifi
ns3::NqosWifiMacHelper m_wifiMacHelper; // a wifi mac helper apply to setup vehicles Wifi
ns3::YansWifiPhyHelper m_wifiPhyHelper; // a wifi phy helper apply to setup vehicles Wifi
std::string m_phyMode;
double m_rss; // -dBm
bool m_init_done;
public:
BaseWifi();
virtual void init();
ns3::NetDeviceContainer Install(ns3::NodeContainer &c);
virtual ~BaseWifi();
};
BaseWifi::BaseWifi() {
m_init_done = false;
m_rss = -80;
m_phyMode ="DsssRate1Mbps";
// TODO Auto-generated constructor stub
init();
}
void BaseWifi::init() {
NS_LOG_UNCOND("inside BaseWifi::init()");
m_wifiHelper.SetStandard (ns3::WIFI_PHY_STANDARD_80211b);
m_wifiPhyHelper = ns3::YansWifiPhyHelper::Default ();
// This is one parameter that matters when using FixedRssLossModel
// set it to zero; otherwise, gain will be added
m_wifiPhyHelper.Set ("RxGain", ns3::DoubleValue (0) );
// ns-3 supports RadioTap and Prism tracing extensions for 802.11b
m_wifiPhyHelper.SetPcapDataLinkType (ns3::YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
ns3::YansWifiChannelHelper wifiChannel;
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
// The below FixedRssLossModel will cause the rss to be fixed regardless
// of the distance between the two stations, and the transmit power
wifiChannel.AddPropagationLoss ("ns3::FixedRssLossModel","Rss",ns3::DoubleValue (m_rss));
m_wifiPhyHelper.SetChannel (wifiChannel.Create ());
// Add a non-QoS upper mac, and disable rate control
m_wifiMacHelper = ns3::NqosWifiMacHelper::Default ();
m_wifiHelper.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
"DataMode",ns3::StringValue (m_phyMode),
"ControlMode",ns3::StringValue (m_phyMode));
// Set it to adhoc mode
m_wifiMacHelper.SetType ("ns3::AdhocWifiMac");
m_init_done = true;
}
//Install the class's embedded settings on the nodes in this node container.
ns3::NetDeviceContainer BaseWifi::Install(ns3::NodeContainer &nc) {
return m_wifiHelper.Install(m_wifiPhyHelper, m_wifiMacHelper, nc);
}
I have run into these kind of issues before. Apparently the initialization of static member objects very much depends on where the implementation is done in your code and (probably) on how the whole thing is compiled. The solution that I found (somewhere) to the problem was to wrap the whole thing into a static member function like this:
//in Agent.h
class Agent : public ns3::Object{
private:
//...
static BaseWifi& m_wifi();
//...
};
and:
//in Agent.cpp
BaseWifi& Agent::m_wifi() {
static BaseWifi TheObject=BaseWifi();
return TheObject;
}
This way the object is initialized properly the first time the static member function is called.
The difference here is the first approach is using copy constructor to initialize the object while the second is using the default constructor.

Debug assertion failed - Vector iterator not dereferencable

I have got this Runtime Error when running this code:
void AlienShipManager::Update(float timeDelta,
BulletManager* bulletManager,
ParticleManager* particleManager,
GameStringSystem* stringBatch)
{
unsigned int i = 0;
while (i < m_alienShipList.size())
{
AlienResult result = m_alienShipList[i].Update(timeDelta, bulletManager);
switch (result)
{
case AlienResult::Dead:
break;
default:
break;
}
++i
}
}
in line
AlienResult result = m_alienShipList[i].Update(timeDelta, bulletManager);
There is how I add AlienShip to vector class:
m_alienShipList.push_back(AlienShip(position, speed, m_screeSize, m_alienShipTexture));
error also appers if I chance that to:
AlienShip* newAlien = new AlienShip(position, speed, m_screeSize, m_alienShipTexture);
m_alienShipList.push_back(*newAlien);
delete newAlien;
but does not appear if I change that to:
AlienShip* newAlien = new AlienShip(position, speed, m_screeSize, m_alienShipTexture);
m_alienShipList.push_back(*newAlien);
which hence lead to huge memory leaks.
This is how looks my AlienShip class:
#pragma once
#include "Body.h"
#include "BulletManager.h"
#include "ParticleManager.h"
enum AliensShipState
{
flying,
dying,
dead,
escaped
};
enum AlienResult
{
No,
Hit,
Dying,
Dead,
Escaped
};
class AlienShip : public Body
{
public:
AlienShip(void);
AlienShip(float2& position, float2& speed, float2* screenSize, ID3D11Texture2D* alienTexture);
~AlienShip(void);
AlienResult Update(float timeDelta, BulletManager* bulletManager);
void Draw(BasicSprites::SpriteBatch^ spriteBatch);
protected:
float m_baseY;
AliensShipState m_state;
float2* m_screenSize;
};
AlienShip class is inherited from Body class, which has Sprite class inside it, which has another vector inside it.
But since Sprite class is working perfectly elsewhere, I don't think it is source of error.
I wonder why this happens, because I can't find the relationship between deleting temporary object and corrupting vector iterator, If it corrupted at all.
Also program compiles and runs in Release, but with some data corruption.
I am using Visual Studio 2012 Beta for Windows 8.
Please write if you need more source code.
Unfortunately it is very hard to post all code, as this is complex program.
Given that it doesn't work when you add the item to the vector by value but it does when you leak a pointer, I have 95% confidence that your copy constructor for AlienShip does a shallow copy, causing your problems.
EDIT: Note that m_alienShipList.push_back(AlienShip(position, speed, m_screeSize, m_alienShipTexture)); causes a copy of your class and if the copy constructor doesn't work right it will cause problems later.
In fact if the AlienShip definition you've pasted is correct there is in fact only the default copy constructor which likely does the wrong thing (further reinforced by the fact that you have your own destructor).
Either implement a copy constructor that does a deep copy, or more preferably rewrite your class to use RAII to manage the memory for you so that the default copy is correct.

C++ new() crashing before calling ctor

thank you for looking at my problem.
I have an object that is being dynamically created in my program. The creation is part of a loop and the first iteration works fine.
Upon creation, my object base class adds itself to a map.
Here is some sample code :
public class Base {
Base() {
// Add itself to a map
Data::objects[key] = this;
}
}
public class Derived : public Base {
// This ctor only initialize one int field.
Derived() : Base() {};
}
Kinda simple isn't it ?
In my code, I do Derived * d = new Derived(); and for some silly reason, I get a SIGSEGV.
I tried to debug it, but it doesn't even enters the ctor before crashing!
Here is my call stack so you can help me better:
Address: #0x002c0000
ntdll!RtlReleasePebLock()
Address: #0x0000000c at c:...\stl_deque.h:514
msvrct!malloc()
libstdc++-6!_Znwj()
fu87_ZSt4cerr(this=0xbc1ad8, e="//my object name//") at //my object name//.cpp
... Other are my lines.
Thank you, Micael
{enjoy}
Edit: Adding informations about the map
The map is located in a data class, statically.
// Data.h
class Data {
static map<int, Base*> objects;
}
// Data.cpp
#include "Data.h"
map<int, Base*> Data::objects;
// methods implementations
How can you corrupt the heap, how can I find a corruption has occured?
Has Data::objects been initialized prior to the creation of ANY of the usages of Base?
You are not guaranteed that the class object objects had been initialized whenever you have more than one translation unit (read, .cpp file) in the final link target, unless you've gone to special effort to ensure it.
Most people solve this problem by using a static class through which this initialization is guaranteed to have occurred on first use. Something like:
// untested code, typed in by hand, not compiled through a machine compiler.
class Base {
public: static addObject(Base* that);
Base::Base() { Base::addObject(this); }
};
class Derived: public Base {
Derived::Derived() {}
};
//
// and in the .CPP for Base
namespace /* hidden */ {
int object_number = 0;
map<int,Base*> *objects = NULL;
}
void Base::addObject(Base* that) {
// TODO: do something to avoid multi-thread issues if that is ever a concern
if (!objects) {
objects = new map<int,Base*>();
}
(*objects)[++object_number] = that;
}
You've probably corrupted the heap at some point prior to the allocation, which causes the crash. Try running with valgrind to see where you're going wrong

Vector Troubles in C++

I am currently working on a project that deals with a vector of objects of a People class. The program compiles and runs just fine, but when I use the debugger it dies when trying to do anything with the PersonWrangler object. I currently have 3 different classes, one for the person, a personwrangler which handles all of the people collectively, and a game class that handles the game input and output.
Edit: My basic question is to understand why it is dying when it calls outputPeople. Also I would like to understand why my program works exactly as it should unless I use the debugger. The outputPeople function works the way I intended that way.
Edit 2: The callstack has 3 bad calls which are:
std::vector >::begin(this=0xbaadf00d)
std::vector >::size(this=0xbaadf00d)
PersonWrangler::outputPeople(this=0xbaadf00d)
Relevant code:
class Game
{
public:
Game();
void gameLoop();
void menu();
void setStatus(bool inputStatus);
bool getStatus();
PersonWrangler* hal;
private:
bool status;
};
which calls outputPeople where it promptly dies from a baadf00d error.
void Game::menu()
{
hal->outputPeople();
}
where hal is an object of PersonWrangler type
class PersonWrangler
{
public:
PersonWrangler(int inputStartingNum);
void outputPeople();
vector<Person*> peopleVector;
vector<Person*>::iterator personIterator;
int totalPeople;
};
and the outputPeople function is defined as
void PersonWrangler::outputPeople()
{
int totalConnections = 0;
cout << " Total People:" << peopleVector.size() << endl;
for (unsigned int i = 0;i < peopleVector.size();i++)
{
sort(peopleVector[i]->connectionsVector.begin(),peopleVector[i]->connectionsVector.end());
peopleVector[i]->connectionsVector.erase( unique (peopleVector[i]->connectionsVector.begin(),peopleVector[i]->connectionsVector.end()),peopleVector[i]->connectionsVector.end());
peopleVector[i]->outputPerson();
totalConnections+=peopleVector[i]->connectionsVector.size();
}
cout << "Total connections:" << totalConnections/2 << endl;
}
Where hal is initialized
Game::Game()
{
PersonWrangler* hal = new PersonWrangler(inputStartingNum);
}
0xBAADFOOD is a magic number to alert you to the fact that you're dealing with uninitialized memory. From the stack trace, we see that this in PersonWrangler::outputPeople is invalid. Thus hal doesn't point to a valid PersonWrangler (that is, assuming frame 4 is a call to Game::menu). To resolve this sort of thing yourself, step through the code, starting at Game::Game(), examining Game::hal as you go, to see what might be going wrong.
In Game::Game, hal is a local variable that shadows Game::hal. When Game::Game exits, this hal goes out of scope and leaks memory, while Game::hal remains uninitialized. What you want is:
Game::Game()
{
hal = new PersonWrangler(inputStartingNum);
}
Debuggers fill uninitialized memory with magic numbers to make it easier to spot errors. In a production build, memory isn't filled with anything in particular; the content of uninitialized memory is undefined, and might hold valid values. This is why a production build might not fail when a debug build will.
Did you initialize hal to point to an actual PersonWrangler object?
Creating a pointer does not point it at an actual object unless you do it explicitly. You probably want to either pass a PersonWrangler to your Game at construction time, or have the Game constructor create a PersonWrangler using new. If you choose the latter, make sure to delete your PersonWrangler somewhere, probably in the Game deconstructor.