Program crushing,when i trying to change class variable
for example:
class ITask
{
public:
ITask();
void perform(int,int);
private:
int total = 0;
}
__________implementation___________
void ITask::perform(int a,int b)
{
int time=rand()%10;
this->total=time;
}
Without string this->total=time; program works.
As you said, you use ITask* task; task->perform(a,b);. However, ITask* task; only declares a pointer to an ITask, it does not create an instance. So your perform member function tries to write to a memory location where it thinks total resides, but in fact the memory is not allocated for that purpose. Hence the crashing which depends on the presence of the line this->total=time;. Note however that the fact that it works without that line is purely implementation defined, as it is still undefined behavior to call a non-static member function without an instance, i.e. without a valid this pointer.
Either use
ITask task;
task.perform(a,b);
(to create an ITask local to the function) or
ITask* task = new ITask();
task->perform(a,b);
//later deallocate:
delete task;
(to create an ITask that lives until you call the delete). Both create actual objects.
Related
I have a simple abstract base class:
class Sensor {
protected:
GenericDriver *driver;
public:
Sensor() {};
virtual void startNewReadout(void) = 0;
};
From which I derive a concrete class:
class OneWireSensor : public Sensor {
private:
OneWireDriver oneWireDriver; //not really necessary here
public:
OneWireSensor(PinData *pinData);
void startNewReadout(void){
this->driver->driverStartReadout();
}
};
Now, when I use the below constructor, my code compiles and runs just as expected:
OneWireSensor::OneWireSensor(PinData *pinData) : oneWireDriver(OneWireDriver(pinData)) {
this->driver = &oneWireDriver;
}
However, the field oneWireDriver is not used anywhere in my code and I don't want to set it. But when I remove it from the OneWireSensor class and use a constructor as follows:
OneWireSensor::OneWireSensor(PinData *pinData) {
OneWireDriver oneWireDriver(pinData);
this->driver = &oneWireDriver;
}
The code compiles fine but the execution ends in a runtime exception (a system hard fault since I am on embedded). GenericDriver is an abstract class from which OneWireDriver class inherits.
What am I doing wrong in the second case?
The problem is most likely caused by the dangling pointer from the constructor of OneWireSensor.
OneWireSensor::OneWireSensor(PinData *pinData) {
// A function local object.
OneWireDriver oneWireDriver(pinData);
// Pointer to the function local object.
// It becomes a dangline pointer as soon as the function returns.
this->driver = &oneWireDriver;
}
You need to use a dynamically allocated object.
OneWireSensor::OneWireSensor(PinData *pinData) {
this->driver = new OneWireDriver(pinData);
}
But then you'll have to write code to manage the dynamically allocated memory. It'll be better to use a smart pointer instead of a raw pointer. See https://en.cppreference.com/w/cpp/memory for more on smart pointers.
In the problem case oneWireDriver only exists when the constructor is running, then it goes out of scope. Using any pointers to it is undefined behavior.
You are creating the object here:
OneWireSensor::OneWireSensor(PinData *pinData) {
OneWireDriver oneWireDriver(pinData); //<<<------
this->driver = &oneWireDriver;
}
In the scope of the function.
Then you assign its address to a member of the class.
After the function scope ends, the oneWireDriver variable is destroyed. Now the class have a dangaling pointer to nowhere. At some point of the execution you probably try to dereference it hence the RuntimeException.
You need to make sure that the variable will live on after the function will end.
You can allocate it on the heap, you need to remember to deallocate on the destructor.
I know Java but don't have much knowledge of C++. I am trying to write a class for the first 3 statements in main function of the code at https://developers.google.com/v8/get_started.
First I have questions about how objects are created in C++. See the below code.
HandleScope handle_scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
I think in C++ when you declare a variable of a class an instance of the class created at the point. You do not need to use new keyword like in Java. So the first statement would create an instance of HandleScope which will be stored in handle_scope.
Now I do not understand how the second statement would work. With my knowledge the part before = will create a new Persistent object which can be referred by the variable context. Then Context::New() will create a new object and store it in context? Huh, I know I am wrong. But I simply dont get how it would work?
I am trying to write a C++ class for the above. Here is my attempt.
class MyClass {
private:
HandleScope handle_scope;
Persistent<Context> context;
Context::Scope context_scope;
public:
MyClass();
};
MyClass::MyClass()
{
context = Context::New();
context_scope = new Context::Scope(context);
}
Have I done the initialization properly?
EDIT: Reply to peachykeen (in comments)
I did the following experimentation.
I wrote a Test class as below.
Test
{
public:
Test() {
cout << "Test" << endl;
}
};
In the main function I wrote Test test; It outputs "Test" which means an object is created without using new keyword.
You are right, in C++, objects are created as soon as they're defined. You do not need to use the new keyword.
However, unlike in Java, objects can be created with different kinds of duration. Using new creates an object on the heap, with dynamic storage duration: the variable lives until you explicitly delete it. (And new returns a pointer to the created object, so that you can track it)
If you simply define an object, as in your first and third lines, then it is created with automatic storage duration: that is, the object exists until it goes out of scope.
This means that you can create objects inside a function, and be guaranteed that they'll be destroyed as soon as you leave the function -- regardless of how you leave the function. Whether you return, or throw an exception, all objects with automatic storage duration (created without using new) are guaranteed to be properly cleaned up.
This means that you should always avoid new whenever possible. If you have to use new, you should typically wrap the resulting pointer into a smart pointer class, an object created with automatic storage duration, so that it gets destroyed automatically). The smart pointer will then call delete on the new-allocated object automatically, ensuring, again, that you don't leak memory.
This distinction is a very powerful tool, which good C++ programmers need to understand well. It is a key to avoiding memory leaks, or more generally, resource leaks of all kinds, and it is, in some respects, more powerful than Java's garbage collector.
For example, say we wish to open a file, and then write some data to it. In C++, we can do it like this:
void foo() {
std::ofstream file("foo.txt");
doStuff(file); // call a function which does something with the file
}
And because file was declared without using new, because it has automatic storage duration, we are guaranteed that it will have its destructor invoked when it goes out of scope, and it will be properly cleaned up -- that is, the stream will be flushed, and the file handle will be closed.
It doesn't matter if doStuff might throw an exception. No matter how we leave foo, file will be properly destroyed, so we don't need to mess about with try/finally like you would in Java. The class is exception-safe by itself, without requiring any additional effort from the user.
Try writing a similar snippet in Java, one which guarantees that even if doStuff throws an exception, the file will be immediately closed. It'll be much longer, and requires more care on the part of the user.
Persistent<Context> context = Context::New();
create object of type Persistent<Context>, initialized from returned of Context::New, if c-tor is not explicit.
Simple example.
#include <iostream>
class C
{
public:
C(int)
{
std::cout << "C::C(int)" << std::endl;
}
};
int main()
{
C c = 1;
}
your class should be
class MyClass {
private:
HandleScope handle_scope;
Persistent<Context> context;
Context::Scope context_scope;
public:
MyClass();
};
MyClass::MyClass():context(Context::New()),
context_scope(Context::Scope(context))
{
}
if Context::Scope is not pointer.
This would be the equivalent class:
class MyClass {
private:
HandleScope handle_scope;
Persistent<Context> context;
Context::Scope context_scope;
public:
MyClass();
};
MyClass::MyClass()
: context(Context::New()),
context_scope(context)
{
}
When you write a statement like this:
Persistent<Context> context = Context::New();
You are constructing context using the copy constructor. This is different from creating the object and then assigning a new value, although the result might often be equivalent.
Likewise this statement:
Context::Scope context_scope(context);
is constructing context_scope and passing context to the constructor. You get the equivalent behavior in a class using the constructor initializer syntax as in my example.
To create an instance of an object, you need only this: Type name; The newkeyword creates a pointer to an object. Normally, to initialize the object, we use parenthesis: Type name(parameter); Sometimes, when an object supports copying, you can use a function that returns an object and assign it to that object: Type name = Some_function_that_returns_Type(); You can now use name like any other object. If you say Type name = new Type;, you will get a compiler error. The keyword new returns a pointer. It would be correct to say Type * name = new Type;. (Note the *, saying that it is a pointer to a Type class, named name. When I refer to Type it is any object, such as your HandleScope. When I refer to name, it is the new object you are creating. The all of all is this: new is a completely different keyword that refers to pointers. If you are not using pointers, don't use it. Use the basic format Type name(parameter, another_param);.
I'm trying to make each instance of a class (named Caller here) have an instance of another class (Target). The point is that the second class has numerous children and I need to be able to have the Caller class switch among them at will. I have tried several ways, but not one gave me any desirable results. Current code:
class Target
{
public:
virtual void do_something()
{ log_message("NO!"); }
};
class TargetChild : public Target
{
public:
virtual void do_something()
{ log_message("YES!"); }
};
class Caller
{
private:
Target target;
public:
void call_target()
{ target.do_something(); }
void set_target(Target set_target)
{ target = set_target; }
};
int main( int argc, const char* argv[] )
{
TargetChild targetChild;
Caller caller;
caller.call_target();
caller.set_target(targetChild);
caller.call_target();
}
The wanted result in the log file is "NO! YES!" but instead it writes the NO! twice. I can't really see what's wrong with it.
You cannot change the type of an object in C++. You can only create, destroy, copy, and (in C++11) move data. In this case, you've copied the data from the subclass object to the base class object. This copied an empty subset of an empty subset. The problem you observed is called "slicing."
Probably what you want is a member containing a function pointer that can be changed. virtual gets you a function pointer but it can't be changed. Try std::tr1::function, boost::function or C++11 std::function.
Or, if you really want to go the virtual route, use a Target * pointer. Best to use a smart pointer class such as unique_ptr< Target > (again Boost/TR1/C++11) or std::auto_ptr< Target > (old-fashioned C++03). You can also do it yourself with new and delete, but such code doesn't really work as well, and is only suitable for a little educational tinkering.
Your code is suffering from object slicing. Even though targetChild in main is a TargetChild, it's passed by value to Caller::set_target, which means it's copied to a local variable which has type Target. To get around object slicing in general, you must use pass-by-reference or use pointers.
In this case, since you wish for Caller to access the passed object outside the Caller::set_target method, you should use a pointer. References alone won't work because though you could make Caller::target a reference, you couldn't change the object it referred to.
Pointers introduce memory management problems, as you must ensure the TargetChild is deallocated (otherwise the program has a memory leak), but not too soon (which will cause access violations, most likely crashing your program). The boost library has various smart pointer classes to make this easier. The C++ standard auto_ptr class could also be used, if only one other class should own the TargetChild instance at any one point in time.
Use an interface, ITarget and switch them at will
ITarget
virtual void do_something() { log_message("NO!"); }
Treat everything as Type of ITarget
This a neat way of handling it.
My c++ is rusty :)
Use pointers instead. More about polymorphism: http://www.cplusplus.com/doc/tutorial/polymorphism/
...
class Caller
{
private:
Target* target;
public:
Caller() { target = NULL; }
void call_target() { if (target != NULL) target->do_something(); }
void set_target(Target* set_target) { target = set_target; }
};
int main( int argc, const char* argv[] )
{
....
caller.set_target(&targetChild);
...
}
In set_target you are passing targetChild by value, there you are loosing the chance to call TargetChild::do_something. You need to extend caller to include a reference (or pointer) to the current target, the reference (or pointer) will keep the information about the original TargetChild and then the compiler will still call TargetChild::do_something.
I have a class Message and a class Cache.
In Message::processMessage() fn. I create a instance of another class CacheRef(not shown below.)
then I call Cache::cacheData(cacheRef)
Now, in Cache class, I have a map which has its key as CacheReference. I store the ref that I passed to cacheData fn. in this map.
class Message
{
private:
Key m_key;
public:
void processMessage(int a, int b, Cache *pCache)
{
CacheRef ref(a, b, m_key); //CacheRef is a class defined in same file
//some char *data - do processing an dfill it!!
pCache->cacheData(ref, data);
}
}
class Cache
{
public:
void cacheData(CacheRef &ref, const char* data)
{
CacheDir *dir;
std::map<<CacheRef, CacheDir*>::iterator it = m_dirs.find(ref);
if(it == m_dirs.end())
{
dir = new CacheDir();
m_dirs.insert(ref, dir);
}
}
std::map<CacheRef, CacheDir*> m_dirs; //CacheDir is some class defined in the same file
}
Now, the code is working absolutely fine. But I have this concern(not sure!!) that I am storing some local variable in map, which which cease to exist as soon as processMessage()fn. exits. So, am I accessing some invalid memory, is it just by luck that this code is working.
If this is wrong, what is the best way to achieve this behaviour?
I don't have boost on my system, so can't use shared_ptr for anything.
Because the 1st template parameter is a CacheRef (and not a reference or pointer to a CacheRef) then ref will be copied into the map when you do the insert. Hence, you won't be storing a reference to a local stack variable.
As long as there is an appropriate copy constructor or assignment operator for CacheRef then this will work ok.
As Stephen Doyle pointed out, you are actually storing a copy of the CacheRef in the map, not a reference to the one passed to the cacheData() method.
Whether this causes a problem or not depends on the definition of the CacheRef class. If, for example, a CacheRef holds a pointer or a reference to the Key passed to the constructor, you will end up with an invalid pointer once the Message instance is destroyed.
By the way, since you are storing dynamically allocated objects of CacheDir in Cache::m_dirs, you should make sure to delete all values in the map in the Cache::~Cache() destructor to avoid memory leaks.
I am trying to write a function that will check if an object exists:
bool UnloadingBay::isEmpty() {
bool isEmpty = true;
if(this->unloadingShip != NULL) {
isEmpty = false;
}
return isEmpty;
}
I am pretty new to C++ and not sure if my Java background is confusing something, but the compiler gives an error:
UnloadingBay.cpp:36: error: no match for ‘operator!=’ in ‘((UnloadingBay*)this)->UnloadingBay::unloadingShip != 0’
I can't seem to figure out why it doesn't work.
Here is the declaration for class UnloadingBay:
class UnloadingBay {
private:
Ship unloadingShip;
public:
UnloadingBay();
~UnloadingBay();
void unloadContainer(Container container);
void loadContainer(Container container);
void dockShip(Ship ship);
void undockShip(Ship ship);
bool isEmpty();
};
It sounds like you may need a primer on the concept of a "variable" in C++.
In C++ every variable's lifetime is tied to it's encompassing scope. The simplest example of this is a function's local variables:
void foo() // foo scope begins
{
UnloadingShip anUnloadingShip; // constructed with default constructor
// do stuff without fear!
anUnloadingShip.Unload();
} // // foo scope ends, anything associated with it guaranteed to go away
In the above code "anUnloadingShip" is default constructed when the function foo is entered (ie its scope is entered). No "new" required. When the encompassing scope goes away (in this case when foo exits), your user-defined destructor is automatically called to clean up the UnloadingShip. The associated memory is automatically cleaned up.
When the encompassing scope is a C++ class (that is to say a member variable):
class UnloadingBay
{
int foo;
UnloadingShip unloadingShip;
};
the lifetime is tied to the instances of the class, so when our function creates an "UnloadingBay"
void bar2()
{
UnloadingBay aBay; /*no new required, default constructor called,
which calls UnloadingShip's constructor for
it's member unloadingShip*/
// do stuff!
} /*destructor fires, which in turn trigger's member's destructors*/
the members of aBay are constructed and live as long as "aBay" lives.
This is all figured out at compile time. There is no run-time reference counting preventing destruction. No considerations are made for anything else that might refer to or point to that variable. The compiler analyzes the functions we wrote to determine the scope, and therefore lifetime, of the variables. The compiler sees where a variable's scope ends and anything needed to clean up that variable will get inserted at compile time.
"new", "NULL", (don't forget "delete") in C++ come into play with pointers. Pointers are a type of variable that holds a memory address of some object. Programmers use the value "NULL" to indicate that a pointer doesn't hold an address (ie it doesn't point to anything). If you aren't using pointers, you don't need to think about NULL.
Until you've mastered how variables in C++ go in and out of scope, avoid pointers. It's another topic entirely.
Good luck!
I'm assuming unloadingShip is an object and not a pointer so the value could never be NULL.
ie.
SomeClass unloadingShip
versus
SomeClass *unloadingShip
Well, you don't have to write so much code to check if a pointer is NULL or not. The method could be a lot simpler:
bool UnloadingBay::isEmpty() const {
return unloadingShip == NULL;
}
Plus, it should be marked as "const" because it does not modify the state of the object and can be called on constant instances as well.
In your case, "unloadingShip" is an object of class "UnloadingShip" which is not dynamically allocated (except when the whole class "UnloadingBay" is allocated dynamically). Thus, checking if it equals to NULL doesn't make sense because it is not a pointer.
For checking, if an object exists, you can consider going this way:
create a pointer to your object:
someClass *myObj = NULL // Make it null
and now where you pass this pointer, you can check:
if(!myObj) // if its set null, it wont pass this condition
myObj = new someClass();
and then in case you want to delete, you can do this:
if(myobj)
{
delete myObj;
myObj = NULL;
}
so in this way, you can have a good control on checking whether your object exists, before deleting it or before creating a new one.
Hope this helps!