I have dynamically created an Sensor object with new. However, when I try to use the object, it looks like the Sensor's members are uninitialized. I have verified that the creation and initialization of the object is successful. I don't believe this problem is due to the global object not being static but, changing it doesn't resolve the issue either.
class SensorModule
{
public:
SPI_BUS* spi;
ADX123* accel;
SENSOR* sensor2;
...
public:
SensorModule();
~SensorModule();
public:
sendCommand();
...
}
SensorModule::SensorModule()
{
spi = new SPI_BUS(1,2,3);
accel = new ADX123(spi,4);
sensor2 = new SENSOR(spi,5);
...// more initialization
}
void SensorModule::sendCommand(void){
accel->accelCommand(); // When I debug and stop here, I see that my "this"
// accel pointer are uninitialized
// however, the SensorModule object pointer is
// valid in the heap
}
main.cpp
SensorModule* pModule = NULL;
int main(void)
{
pModule = new SensorModule();
pModule->sendCommand();
...
for(;;)
{}
}
your code seems fine so far, although you have to be very careful to also call delete. In C++ you should usually use unique_ptr to make sure that the elements are deallocated.
Do you debug in debug or release mode? Release mode sometimes messes up some debug symbols. Do you change accel in the course of the constructor or with another method? There has to be something because accel is definitely initialized here. You might also step through the different lines of your constructor to check this.
Related
I have a class which is loaded from an external file, so ideally I would want its constructor to load from a given path if the load fails, I will want to throw an error if the file is not found/not readable (Throwing errors from constructors is not a horrible idea, see ISO's FAQ).
There is a problem with this though, I want to handle errors myself in some controlled manner, and I want to do that immediately, so I need to put a try-catch statement around the constructor for this object ... and if I do that, the object is not declared outside the try statement, i.e.:
//in my_class.hpp
class my_class
{
...
public:
my_class(string path);//Throws file not found, or other error error
...
};
//anywhere my_class is needed
try
{
my_class my_object(string);
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
//Problem... now my_object doesn't exist anymore
I have tried a number of ways of getting around it, but I don't really like any of them:
Firstly, I could use a pointer to my_class instead of the class itself:
my_class* my_pointer;
try
{
my_class my_pointer = new my_class(string);
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
The problem is that the instance of this object doesn't always end up in the same object which created it, so deleting all pointers correctly would be easy to do wrong, and besides, I personally think it is ugly to have some objects be pointers to objects, and have most others be "regular objects".
Secondly, I could use a vector with only one element in much the same way:
std::vector<my_class> single_vector;
try
{
single_vector.push_back(my_class(string));
single_vector.shrink_to_fit();
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
I don't like the idea of having a lot of single-element vectors though.
Thirdly, I can create an empty faux constructor and use another loading function, i.e.
//in my_class.hpp
class my_class
{
...
public:
my_class() {}// Faux constructor which does nothing
void load(string path);//All the code in the constructor has been moved here
...
};
//anywhere my_class is needed
my_class my_object
try
{
my_object.load(path);
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
This works, but largely defeats the purpose of having a constructor, so I don't really like this either.
So my question is, which of these methods for constructing an object, which may throw errors in the constructor, is the best (or least bad)? and are there better ways of doing this?
Edit: Why don't you just use the object within the try-statement
Because the object may need to be created as the program is first started, and stopped much later. In the most extreme case (which I do actually need in this case also) that would essentially be:
int main()
{
try
{
//... things which might fail
//A few hundred lines of code
}
catch(/*whaveter*/)
{
}
}
I think this makes my code hard to read since the catch statement will be very far from where things actually went wrong.
One possibility is to wrap the construction and error handling in a function, returning the constructed object. Example :
#include <string>
class my_class {
public:
my_class(std::string path);
};
my_class make_my_object(std::string path)
{
try {
return {std::move(path)};
}
catch(...) {
// Handle however you want
}
}
int main()
{
auto my_object = make_my_object("this path doesn't exist");
}
But beware that the example is incomplete because it isn't clear what you intend to do when construction fails. The catch block has to either return something, throw or terminate.
If you could return a different instance, one with a "bad" or "default" state, you could have just initialized your instance to that state in my_class(std::string path) when it was determined the path is invalid. So in that case, the try/catch block is not needed.
If you rethrow the exception, then there is no point in catching it in the first place. In that case, the try/catch block is also not needed, unless you want to do a bit of extra work, like logging.
If you want to terminate, you can just let the exception go uncaught. Again, in that case, the try/catch block is not needed.
The real solution here is probably to not use a try/catch block at all, unless there is actually error handling you can do that shouldn't be implemented as part of my_class which isn't made apparent in the question (maybe a fallback path?).
and if I do that, the object is not declared outside the try statement
I have tried a number of ways of getting around it
That doesn't need to be a problem. There's not necessarily need to get around it. Simply use the object within the try statement.
If you really cannot have the try block around the entire lifetime, then this is a use case for std::optional:
std::optional<my_class> maybe_my_object;
try {
maybe_my_object.emplace(string);
} catch(...) {}
The problem is that the instance of this object doesn't always end up in the same object which created it, so deleting all pointers correctly would be easy to do wrong,
A pointer returned by new is correct to delete. In the error case, simply set the pointer to null and there would be no problem. That said, use a smart pointer instead for dynamic allocation, if you were to use this approach.
single_vector.push_back(my_class(string));
single_vector.shrink_to_fit();
Don't push and shrink when you know the number of objects that are going to be in the vector. Use reserve instead if you were to use this approach.
The object creation can fail because a resource is unavailable. It's not the creation which fails; it is a prerequisite which is not fulfilled.
Consequently, separate these two concerns: First obtain all resources and then, if that succeeded, create the object with these resources and use it. The object creation as such in this design cannot fail, the constructor is nothrow; it is trivial boilerplate code (copy data etc.). If, on the other hand, resource acquisition failed, object creation and object use are both skipped: Your problem with existing but unusable objects is gone.
Responding to your edit about try/catch comprising the entire program: Exceptions as error indicators are better suited for things which are done in many places at various times in a program because they guarantee error handling (by default through an abort) while separating it from the normal control flow. This is impossible to do with classic return value examination, which leaves us with a choice between unreadable or unreliable programs.
But if you have long-lived objects which are created only rarely (in your example: only at startup) you don't need exceptions. As you said, constructor exceptions guarantee that only properly initialized objects can be used. But if such an object is only created at startup this danger is low. You check for success one way or another and exit the program which cannot perform its purpose if the initial resource acquisition failed. This way the error is handled where it occurred. Even in less extreme cases (e.g. when an object is created at the beginning of a large function other than main) this may be the simpler solution.
In code, my suggestion looks like this:
struct T2;
struct myEx { myEx(const char *); };
void exit(int);
T1 *acquireResource1(); // e.g. read file
T2 *acquireResource2(); // e.g. connect to db
void log(const char *what);
class ObjT
{
public:
struct RsrcT
{
T1 *mT1;
T2 *mT2;
operator bool() { return mT1 && mT2; }
};
ObjT(const RsrcT& res) noexcept
{
// initialize from file data etc.
}
// more member functions using data from file and db
};
int main()
{
ObjT::RsrcT rsrc = { acquireResource1(), acquireResource2() };
if(!rsrc)
{
log("bummer");
exit(1);
}
///////////////////////////////////////////////////
// all resources are available. "Real" code starts here.
///////////////////////////////////////////////////
ObjT obj(rsrc);
// 1000 lines of code using obj
}
I'm trying to understand some code that is for an ESP32 EPaper module(TTGO T5 V2.2). This program makes use of the Button2 library for handling events when one of the three buttons is pressed. It initializes an object for each button and stores it in an array of pointers. when I want to compile the code, I get the following error:
error: no matching function for call to 'Button2::Button2()'
(info: Button2 *pBtns = nullptr; args = 3; )
The codeline where the error occures is:
pBtns = new Button2 [args];
So far I understood, should this line reserve the memory on the heap for that new object. So why should there be a function and what's the purpose of it?
I tried so far using a fixed array size and use a sniplet from some example found somewhere on the internet:
//Button2 pBtns[5] = {nullptr,nullptr,nullptr,nullptr,nullptr};
//Button2 pBtns[5];
//Button2* pBtns = static_cast<Button2*>( ::operator new ( sizeof(Button2) * (sizeof(g_btns) / sizeof(g_btns[0]))));
// g_btns[] is the array of gpio pins of the buttons
Due to the lack of examples I have still no clue if I am missing something, but the "no matching function for call"-error hints to a problem with the object itself, if I'm not wrong ...
// in Button2.h:
class Button2 {
private:
.// some private defs ...
public:
Button2(byte attachTo, byte buttonMode = INPUT_PULLUP, unsigned int debounceTimeout = DEBOUNCE_MS);
.// some methods here ...
bool operator==(Button2 &rhs);
void loop();
};
// in program code:
#define BUTTONS_MAP {37,38,39}
Button2 *pBtns = nullptr;
uint8_t g_btns[] = BUTTONS_MAP;
void button_init()
{
uint8_t args = sizeof(g_btns) / sizeof(g_btns[0]);
pBtns = new Button2 [args]; //<<<<<<< COMPILER-ERROR is HERE
//pBtns = new Button2;
for (int i = 0; i < args; ++i) {
pBtns[i] = Button2(g_btns[i]);
pBtns[i].setPressedHandler(button_callback);
}
}
I want in the above example that pBtns contains an array with 3 Pointers to new created and initialized objects. Additionaly I want to know what function is ment in the error message. I like the idea of storing objects in arrays and want to use it in my own development, when I understood the principle and practised - so what are the pros and cons of technique?
(sri for the long text - just don't yet know whats relevant, so pimp my brain!)
When an array is allocated, the program will attempt to default construct the elements.
You cannot default construct Button2 because defining another constructor disables the automatically generated default constructor. You need to either add a default constructor or move to a smarter container like std::vector.
Example:
Button2 *pBtns = nullptr;
becomes
std::vector<Button2> btns;
And then later buttons are created in the vector with
btns.emplace_back(<arguments>);
As an added bonus, vector removes all of the memory management work that a dynamically allocated array saddles you with.
The problem is the lack of default (no argument) constructor called by operator new [].
To define one add this line to the class Button2 definition:
Button2() = default; // after C++11
or
Button2() {} // before C++11
Assuming all your members also have default constructors (most likely), this should JustWork(TM)
Button2 *pBtns is not an array of pointers, but a pointer to one or more actual Button2 objects. That is why new[] tries to construct such objects.
You would need
Button2 **pBtns=nullptr;
...
pBtns=new *Button2[args];
and then could the loop with pBtns[i]=new Button2(...); work.
But this is rather C-ish (minus the use of new), contemporary C++ code would more likely use std::vector, as comments and other answer(s) suggest.
I'm trying to use Google's protobuf.
I use a subMessage, I set it with random values and store the subMessage in the mainMessage. Here are example messages that fit my case :
message subMessage{
required int32 val1= 1;
required int32 val2= 2;
required int32 val3= 3;
required int32 val4= 4;
}
message mainMessage{
required subMessage sub = 1;
}
My main :
int main (int argc,char** argv){
subMessage sM;
mainMessage mM;
sM.set_val1(10);
sM.set_val2(9);
sM.set_val3(8);
sM.set_val4(7);
I then tried :
mM.set_allocated_submessage(&sM);
but it result in a segmentation fault at the end of the program (Destruction of the object ?). The only way to solve it is to manually call mM.release_submessage();.
I also tried :
*mM.mutable_submessage()=subMessage;
I don't get why I have a segmentation fault as my program stops right after (Nothing accessing/writing on my subMessage or my mainMessage).
According to Google's documentation :
void set_allocated_foo(Bar* bar): Sets the Bar object to the field and frees the previous field value if it exists. If the Bar pointer is not NULL, the message takes ownership of the allocated Bar object and has_foo() will return true. Otherwise, if the Bar is NULL, the behavior is the same as calling clear_foo()
It seems that mainMessage has the ownership after set_allocated_foo(), but it results in a Segmentation fault. In the other hand, the mutable_foo() seems to duplicate the data. I would like to avoid duplicating datas as I'm going to run on Raspberry with low RAM, but the set_allocated_foo() is too mysterious for me for the moment. I don't get the difference between theses two...
Do you think I should use .set_allocated_foo() and manually release it, or use .mutable_foo() ?
Thanks.
PS : I'm aware of this topic about set_allocated_foo() but my problem isn't about deleting or not but more about rights on the pointers/datas and didn't help me solving my problem
Your code deletes LOCAL variable by delete operator. This is undefined behaviour. Your problem is that you are passing pointer to LOCAL variable, you should allocate subMessage by new then you can pass it into mainMessage.
int main()
{
subMessage sM; // [1]
mainMessage mM;
sM.set_val1(10);
sM.set_val2(9);
sM.set_val3(8);
sM.set_val4(7);
mM.set_allocated_submessage(&sM); // [2]
// calls dtors in reverse order of definitions of instances
dtor on mM is called // [3]
dtor on sM is called // [4]
}
In short:
[1] sM is created as local variable
[2] you are passing pointer to local variable sM, in this moment mM takes ownership of sM
[3] and because mM took ownership of sM it tries to delete sM in dtor by calling delete ptrToSm
[4] probably this point is never reached, app crashed
Solution:
subMessage* sM = new ...;
mM.set_allocated_submessage(sM);
I have recently encountered a scope technique in Cinder -- a graphics library:
{
gl::ScopedModelMatrix scpModelMatrix;
//.... Anything in this area will be executed in ModelMatrix-mode.
// (if applicable)
}
//.... In this area, there is no ModelMatrix-mode effect.
Let's assume that this technique is implemented by:
The constructor (at the beginning of the scope);
The destructor (at the end of the scope).
(Thank, Klitos Kyriacou!)
Question
What is the name of this technique?
... I tried to google it, but found no article mentioning this.
What are the disadvantages of this technique?
I planned to do something like:
{
Go* gameObject = sysCreator->createGameObject();
ScopeMarker scope=sysCreator->markScope(gameObject);
Graphic_Object* gra = sysGraphic->create( ... );
Physic_Object* phy = sysPhysic->create( .... );
// "gra" & "phy" will be considered as owned by "gameObject".
// That is : both variables will be deleted automatically ...
// ... when "gameObject" is destroyed.
}
In other words, is there anything of which I should be careful specifically?
Edit2: Thank a lot for many useful comments.
As requested, this is how I will implement it. Roughly speaking,
ScopeMarker SysCreator::markScope(GameObject* gameObject){
sysGraphic->notify( gameObject );
sysPhysic->notify( gameObject );
ScopeMarker scope= ScopeMarker(this);
}
int counter=0; // counter for scope constructor (+1), destructor (-1)
// .... other code to manage Constructor / Destructor of ScopeMarker ...
Every time new graphic/physic object created, it will be marked as owned by the game object.
void SysGraphic::notify(GameObject* gameObject){
this->cacheGO=gameObject;
}
Graphic_Object* SysGraphic::create( some parameter ){
Graphic_Object* gra = create_( some parameter);
sysOwnerBinder->markOwner( this->cacheGO, gra ); //another system
}
//Every timestep,
// sysOwnerBinder will check find every "gameObject" that will be deleted.
// It will delete its "gra" & "phy" first.
Note that I don't use any static variables / function.
Reference: https://libcinder.org/docs/structcinder_1_1gl_1_1_scoped_depth_test.html
I'm having a debug only crash. I'm using Eclipse's gdb.
If I'm not failing reading it, the crash seems to occur when passing an object (not by reference nor pointer) to an interface method, precisely when copying a "many" (typedef std::list<boost::any> many;) member during it's copy constructor called to send a copy to the method.
I'm not using debug builds for boost, nor other external builds, just for the code I'm compiling, so, could this be the cause?
Any other ideas at what may be the cause?
class Message {
public:
static const int MAX_LEVEL=5;
Message(int type=0, int destination=0);
virtual ~Message();
int type;
int destination[MAX_LEVEL];
int level;
many message;
};
And the crashing sector, inside init() on Game3DWin: (Even though I'm building in Debug mode, there's no _DEBUG define since I didn't build the Debug binaries for the libs)
bool Game3DWin::init(){
#ifdef _DEBUG
pluginsCfg = "lib/plugins_d.cfg";
resourcesCfg = "res/resources_d.cfg";
#elif OGRE_PLATFORM == OGRE_PLATFORM_WIN32
pluginsCfg = "lib/pluginsWin.cfg";
resourcesCfg = "res/resources.cfg";
#else
pluginsCfg = "lib/plugins.cfg";
resourcesCfg = "res/resources.cfg";
#endif
ogreRoot=boost::make_shared<Ogre::Root>(pluginsCfg, "config.cfg");
if(!(ogreRoot->restoreConfig() || ogreRoot->showConfigDialog())){
return false;
}
window = ogreRoot->initialise(true, "Crewon CLASH!");
loadResourceCfgFile();
guiRenderer = &CEGUI::OgreRenderer::bootstrapSystem();
CEGUI::SchemeManager::getSingleton().create( "TaharezLook.scheme" );
CEGUI::System::getSingleton().setDefaultFont( "DejaVuSans-10" );
CEGUI::System::getSingleton().setDefaultMouseCursor( "TaharezLook", "MouseArrow" );
CEGUI::Window* myRoot = CEGUI::WindowManager::getSingleton().createWindow( "DefaultWindow", "_MasterRoot" );
CEGUI::System::getSingleton().setGUISheet( myRoot );
CRengine::Message msg=CRengine::Message( (int)CRengine::MESSAGE_TYPE::INPUT_INIT );
msg.message.push_front(window);
this->broadcaster.lock()->receiveMessage( msg ); //Crash here
//Unreached code due to crash
}
broadcaster is a pointer to Messageable, an interface.
class Messageable {
public:
virtual ~Messageable() {};
virtual bool receiveMessage(CRengine::Message) = 0;
};
broadcaster initialization (factory method to be able to store a "this" smart pointer):
Game3DWin* Game3DWin::create(boost::shared_ptr<CRengine::Messageable> caster, int processType, int order){
Game3DWin* temp= new Game3DWin(processType, order);
temp->broadcaster=caster;
bool success=temp->init();
if(!success){
delete temp;
temp=NULL;
}else{
temp->checkRoom(); }
return temp;
}
The above is called here:
bool MainManager::start( boost::shared_ptr<MainManager> thisMM ){
//Some code
boost::shared_ptr<Game3DWin> win;
win.reset( Game3DWin::create(thisMM, CRengine::MAIN_PROCESS_TYPES::PROCESS_GUI) );
//Some code
}
start() called from the main, which passes the pointer to MainManager
boost::shared_ptr<CRengine::MainManager> app =boost::make_shared<CRengine::MainManager>();
app->start(app);
Message implementation:
Message::Message(int type, int destination): type(type), level(0){
for(int ii=0;ii<MAX_LEVEL;ii++){
this->destination[ii]=-1;
}
this->destination[0]=destination;
}
Message::~Message() { }
window is Ogre::RenderWindow* from OGRE 3D open source rendering engine. I tried to cast it to (int) before pushing it into many in case it tried to call a destructor or something, but, still, same crash.
This is an extended comment, too long to fit in a comment.
Message lacks an implemented constructor and destructor. Either simplfy the class while confirming the problem still occurs, or expose that implementation to us.
window is a variable of unknown type. As the list of boost::any that you are reporting as crashing contains the window type, knowing what it is may just be somewhat useful.
this->broadcaster.lock() will be a null shared_ptr if the weak_ptr has gone away. Always, always, always do shared_ptr<foo> pFoo = this->broadcaster.lock(); then use pFoo (or whatever name) after checking that it is valid (evaluating it in a boolean context).
boost::weak_ptr<CRengine::Messageable> caster -- do you not know if this exists? You probably want a boost::shared_ptr here, so that the caster is at least known to exist during creation of the Game3DWin.
Same here: boost::weak_ptr<MainManager> thisMM -- probably should be a shared_ptr.
The issue was none of the aforementioned. It was caused by Eclipse being unable to clean. This was caused due to using "External Builder", mingw32-make.exe, which in the makefile ran a del <Filelist> and Windows7 seems to have some issue with this and it's parameters, so the clean did nothing.
Since I was working with Debug as active build, I got the crash due to lack of clean, but when I switched to Release it was unaffected since it had to mostly rebuild everything.
Manual delete of the contents of <project>/Debug and <project>/Release fixed the problem.