I'm new to programming and game development in general
every time I read and hear that pointers are a nightmare I want to ask if it is necessary to check pointers in such cases as shown below?
// create a component of a certain type and return a pointer to data of this type
StaticMeshCompt = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
if (StaticMeshCompt)
{
// further work with the component
}
No, there's no need to check the pointer. The cases where CreateDefaultSubobject could return nullptr are :
The class passed is nullptr (It's guaranteed to be valid for any UObject).
The class has the abstract flag (Not the case for
UStaticMeshComponent).
Allocation itself fails due to lack of free memory (At that point,
you've got other problems).
As David G and ChrisMM said, it is necessary to check the pointer if the CreateDefaultSubobject function has a possibility of failing or returning a null pointer. If the function is known to always return a valid object, checking may not be necessary in that case.
Related
I have a function that accepts a pointer and return an enum depending on some conditions related to that pointer:
my_enum function(char* prt)
{
/* function body*/
if (condition1) return enum1;
if (condition2) return enum2;
if (condition3) return enum3;
if (condition4) return enum4;
else return enum5;
}
I have another function which also accepts a pointer, invokes my_function and reacts to the obtained value:
void another_function(char* ptr)
{
my_enum result = function(ptr);
if (result == MY_VALUE) std::cout<<"OK"<<endl;
}
I'm running Valgrind to check for memory leaks. The above code results in the following error:
Conditional jump depends on an uninitialized variable.
In fact, it is possible to pass an uninitialized pointer to the function function.
My question is: What is the best way of dealing with this situation (apart from using references instead)? I can't make sure that everyone who will use that code, will initialize the pointer that he will pass to the function. I can't check inside my function if the pointer points to some garbage (I'm checking whether it is a null pointer though) as well.
Should I ignore such errors? If they are useless, why does Valgrind bother to inform me about them? There must be something I can do.
How far are you willing to go? If someone WANTS to break your code, they will, you can't help it.
The more efficient protections you apply the more difficult they get.
The one simple one is to check for NULL. That doesn't prevent stupid pointers, but it prevents ones consciously invalidated. Most people are satisfied by that.
Then you may give the pointer a wrapper class. Instantiating this class requires a valid object pointed to (or some hopeless jumping through hoops to give it an invalid one, which amounts to purposefully shooting your foot), so no scenario of uninitialized pointer can occur - but the object can cease to exist before its pointer is used.
Then you can maintain a factory/manager class for these objects and their pointers. Every time the pointer destination object is created or destroyed, its pointer is created or invalidated. This will be fail-proof unless your code is multi-threading and destruction can occur while your function is already past the checks and before using the validated value.
Then you can add thread safety, wrapping both your function and the manager in mutexes. This adds all kinds of headaches related to deadlocks and synchronization. But the user must really try very hard to create a class derived from yours (probably with #define private public first) that overrides its safety features...
With each step your overhead climbs to levels where the effect really stops being worth the effort. So just check that pointer for NULL and stop worrying about others out to get you.
Opinions will vary on what is the "best" approach, since it is impossible to prevent someone passing a bad (e.g. uninitialised, dangling) pointer at all.
A common solution is to avoid raw pointers altogether, and write the function in a way that does not accept a pointer at all.
One way is to accept a reference. Writing your code so it doesn't use raw pointers at all makes it harder to call your function with a bad parameter. The limitation is that the caller can still create a bad reference (e.g. by dereferencing a bad pointer) but it takes more effort (or a longer sequence of mistakes if done unwittingly) to pass a bad reference to a function than it does to pass a bad pointer.
Another way is to accept some class object by value (or reference, in some cases) to hold your pointer. Then implement all member functions of that so that they prevent a situation of holding a bad pointer. Give that class no member functions that accept a pointer. Ensure the constructors and other member functions maintain consistency (formally, the constructors establish a rigorous set of invariants, other member functions maintain that set of invariants). This includes techniques like throwing an exception if an attempt is made to construct an object using bad data (if an exception is thrown in the process of constructing an object, that object never exists, and cannot be passed in any manner to your function). As a result, your function can assume - if it is successfully called - that the data it receives is valid.
The thing is, the above make it harder to accidentally pass bad data to your function. No technique can absolutely prevent someone who is determined enough (whether through genius or foolishness) to find a way to bypass all the safeguards, and to pass bad data to your function.
There are essentially two solutions.
Expect a valid pointer and state that clearly in the documentation of your API. Then any invalid use will cause UB, but it's not your fault. However, handling raw pointers is C-style and frowned upon by C++ programmers.
Take (the reference to) an encapsulated pointer type, which is always sensibly initialised, such as std::string (instead of const char*), std::unique_ptr, or std::shared_ptr. For example,
my_enum function(std::string const&str)
{
/* function body*/
if (str.empty()) // deal with improper input
std::cerr<<"warning: empty string in function()"<<std::endl;
if (condition1) return enum1;
if (condition2) return enum2;
if (condition3) return enum3;
if (condition4) return enum4;
else return enum5;
}
or
my_enum function(std::unique_ptr<SomeType> const&ptr)
{
/* function body*/
if (!ptr) { // deal with improper input
std::cerr<<"warning: invalid pointer in function()"<<std::endl;
return enum_error;
}
if (condition1) return enum1;
if (condition2) return enum2;
if (condition3) return enum3;
if (condition4) return enum4;
else return enum5;
}
This avoids raw pointers and is the C++ way for dealing with this sort of situation. One problem with the latter code is that it only works for unique_ptr arguments. One may generalise this to be overloaded (using SFINAE or otherwise) to take (const reference to) any auto-pointer like objects (for instance defined as objects obj with member obj::get() const returning a const obj::element_type*).
For some reasons in our application we could have pointers that was already deleted:
IPolymorphicObject* p_object = CreateObject();
Somewhere p_object will be deleted (via either delete or unloading module where it was allocated)
delete p_type;
Another code which uses saved value of p_object, let it be mp_object.
mp_object->SomeMethod();
Since mp_object is already removed - we have a crash.
I know that the best way is to switch to shared_ptr/weak_ptr, but now it requires a lot of refactoring, that is why I found another solution - how to check pointer validity.
I know that dynamic_cast will return pointer to the actual object offset in memory.
Also I know that dynamic_cast(p_invalid_pointer) will throw an exception non_rtti_object which I can catch I thus write validation method:
template<class T>
bool IsPointerValid(T* ip_ptr)
{
try
{
dynamic_cast<void*>(ip_ptr);
}
catch(...)
{
return false;
}
return true;
}
Final code will look like:
if( IsPointerValid(mp_object))
mp_object->SomeMethod();
I know that this will be very bad solution and should be avoided.
My questing is: will IsPointerValid always return false if pointer to polymorphic object is not valid?
This is undefined behavior.
What you need to understand is that dynamic_cast requires a "valid" pointer. That is, a pointer to a "valid" object.
Given a pointer to an invalid object, an object that no longer exists, this results in undefined behavior.
Sometimes you will get true here. Sometimes you will get false. And sometimes you will get "File Not Found" as the return value. That's what undefined behavior means.
While moving to shared/weak_ptr will sure cost you a lot of time, solving the problem, and guaranteeing it won't return, will cost you
a. more time; you'll always end up in the 'I think the problem is solved' state, and never feel safe anymore.
b. customer satisfaction because you're not going to cover 100% of your source code.
I hope you also have NULL-pointers checks prior to dereference those. In this case replace your delete by a macro DELETE which will invoke the real delete and also set the pointer to NULL. This will signal the followed software that the object is deleted and should not be used. In my opinion such replacement should not take significant efforts also in a relatively big project.
If you have a function that returns a pointer to an object by looking for an object with a specific attribute in an array, what should I return if I don't find a corresponding object in the array? And, if done badly, could this represent a risk to the security or stability of the program?
If you have a function that returns a pointer to an object by looking
for an specific attribute into an array of those objects, what should
i return if i don't find that attribute in the array? and if done
badly could this represent a risk to the security or stability of the
program?
You have three basic possibilities:
Simply return a null pointer. This is the easiest way and very probably the best.
Throw an exception. Preferably of a special type, but std::out_of_range might do too.
Return a pointer to a default object. Only reasonable if the return value must to point to a valid object.
Whatever you choose, it must be documented and as consistent to other cases as possible.
You could return nullptr with the convention that the caller should test that case. Or you could throw an exception.
You might use some smart pointers.
With C++11 you could take a different approach: passing a lambda function to deal with the found object.
If you have a function that returns a pointer to an object by looking
for an specific attribute into an array of those objects, what should
i return if i don't find that attribute in the array? and if done
badly could this represent a risk to the security or stability of the
program?
As Columbo said:
You have three basic possibilities:
Simply return a null pointer. This is the easiest way and very probably the best.
Throw an exception. Preferably of a special type, but std::out_of_range might do too.
Return a pointer to a default object. Only reasonable if the return value must to point to a valid object.
However, I disagree on your choice of options. Only the first two can reasonably be considered, unless you are certain you will always return a valid object.
And, if done badly, could this represent a risk to the security or
stability of the program?
Yes. Imagine you select possibility #3 and document it in your API. The caller is expecting a valid object each time. And let's say your app is a critical component of a server and an attacker finds an exploit that results in overwriting data in the table. This will most probably lead to a crash of your app: you get instant denial of service attack. And this really isn't a far fetched scenario…
Without even getting that far, if done badly, you could return invalid pointers, which may lead to app crash. Then again, anything done badly leads to the dark side...
I have a member function with an object type as the return value type:
MyObject myfunction(parameters) {
if (some condition) {
return MyObject(parameters);
} else {
... no valid object can be created ...
}
}
Under certain conditions (checked for in the function body) an object of type MyObject cannot be created and returned.
Beeing just an occasional c++ programmer I can spontaneously come up with three solutions:
Changing the return value type to * MyObject and returning nullptr if no valid object can be created (C++11), then checking for equality to nullptr in the calling code.
Throwing an exception if no object can be created and catching that one in the calling code.
Creating an object with some values that I define as invalid and check for that before using the returned object.
What would be the standard way of dealing with such a situation and the best solution in terms of performance? ... or some obvious work-around that I just don't see ...
A state-of-the-art C++11 solution would be perfect :-)
My thoughts so far:
Solution 1 seems OK, but is C++11 only and I would have to create the returned object on the heap in order to be able to pass it to the main program (returning the object itself to the calling function, thus keeping it in the stack might be quicker for small objects?).
Solution 2 might be slower and leads to verbose coding in the main program.
Solution 3 is probably the slowest (an object is created in vain) and not very convenient to check for in the main program.
For my code no valid return object is rather the default situation than the exception and the created object is rather small, but general considerations considering different cases are certainly useful for other readers' applications ...
Thanks a lot to all of you for help :-)
In the usual case, returning a Boost.Optional works:
boost::optional<MyObject> myfunction(parameters) {
if (some condition) {
return MyObject(parameters);
} else {
return boost::none;
}
}
And at the call site:
auto ret = myfunction(...);
if(ret)
// use '*ret' or 'ret.get()'
But as R. Martinho mentions, there are drawbacks to this solution (namely, move-only types don't work because Boost.Optional is not yet updated to support move-semantics).
All 3 of your suggested solutions are valid and common, depending on the circumstances.
If being unable to create the object is an error condition that is likely to cause the calling function to have to abort, back up and retry, or take other drastic measures, then throw an exception.
If inability to create the object is a routine event, and you expect the caller to check if an object was created and proceed fairly normally in either case, returning null is a good solution.
If there's a reasonable dummy or blank object that can be created, that's a fine solution. But this is pretty rare. You should only do this if the caller will actually process the dummy object.
If you return a null pointer and then you find that every place you call this function you are writing
MyObject* myobject=myfunction(whatever);
if (myobject==null) throw new PanicException;
Then you might as well just throw the exception inside the function.
Worse, if you are writing:
MyObject* myobject=myfunction(whatever);
if (myobject!=null)
{
... process it ...
}
else
{
... display error message ...
}
Then you are just simulating exception handling with an IF statement. Use a real exception.
On the other hand, if you throw an exception and then you find you are regularly writing:
MyObject* myobject;
try
{
myobject=myfunction(whatever);
}
catch (PanicException pe)
{
myobject=null;
}
Well then, you would have been better off to just return the null.
I've occasionally created dummy objects. The most common case is when a function returns a collection, like an array or linked list, and if I find no data to put in the collection, then return a collection with zero elements. Then the caller loops through the elements in the collection, and if there are none, that's just fine. I've had a few cases where I've returned an object with a zero-length string for the name or customer id or whatever. But in general, if you're just returning a dummy object so that the caller can test and say, oh, it's a dummy object, and then throw it away, I think you're better off to return null.
BTW not sure what you meant when you said that you could only return a null pointer in C++11. The ability to pass around nulls goes back to the earliest version of C++ that I ever saw.
Since your question is phrased in generalities, I will also respond in generalities.
If you have a function whose job it is to create and return an object, then that is it's job.
Now if you want to design this function in such a way so that when certian conditions needed to build the object are not met then not return the object, you have actually changed the semantics of this function. Now instead on just one responsibility, it has three:
Determine if the right conditions exist to construct the object
If yes, construct and return the object
If no, return nothing, or some condition value that indicates non-creation
The "Single Responsibility Principle" suggests that in general, good design dictates that one function (or class or what have you) should have one job to do. Here, your function has three.
I would suggest that none of your suggested approaches is best in general. Rather, I would go with:
4: Implement a separate function to determine the eligibility to
construct the object. If that function returns true, then call
myFunction which constructs the object & returns it.
The first solution should be used except if the conditions that prevent the creation of the object are exceptional. Otherwise returning a NULL pointer is a perfectly valid solution... even in C++11.
The "pointer" should of course be wrapped using an RAII container such as a std::unique_ptr. Should be common practice for you code really.
The third solution is a total waste of resources if you ask me. You would have to create an invalid (not useful) object, and copy it for the return value... only for it to be discarded.
This seems like a lot of work; to check for null each time an object is used.
I have been advised that it is a good idea to check for null pointers so you don't have to spend time looking for where segmentation faults occur.
Just wondering what the community here thinks?
Use references whenever you can, because they can't be null, therefore you don't have to check if they are null.
It's good practice to check for null in function parameters and other places you may be dealing with pointers someone else is passing you. However, in your own code, you might have pointers you know will always be pointing to a valid object, so a null check is probably overkill... just use your common sense.
I don't know if it really helps with debugging because any debugger will be showing you pretty clearly that a null pointer was used and it won't take long to find it. It's more about making sure you don't crash if another programmer passes in NULL, or that the mistake is picked up by an assert in a debug build.
No. You should instead make sure the pointers were not set to NULL in the first place. Note that in Standard C++:
int * p = new int;
then p can never be NULL because new will throw an exception if the allocation fails.
If you are writing functions that can take a pointer as a parameter, you should treat them like this
// does something with p
// note that p cannot be NULL
void f( int * p );
In other words you should document the requirements of the function. You can also use assert() to check if someone has ignored your documentation (if they have, it's their problem, not yours), but I must admit I have gone off this as time has gone on - simply say what the function requires, and leave the responsibility with the caller.
A third bit of advice is simply not to use pointers - most C++ code that I've seen overuses pointers to a ridiculous extent - you should use values and references wherever possible.
In general, I would advise against doing this, as it makes your code harder to read and you also have to come up with some sensible way of dealing with the situation if a pointer is actually NULL.
In my C++ projects, I only check if a pointer (if I am using pointers at all) is NULL, only if it could be a valid state of the pointer. Checking for NULL if the pointer should never actually be NULL is a bit pointless, because you are then trying work around some programming error you should fix instead.
Additionally, when you feel the need to check if a pointer is NULL, you probably should define more clearly who owns pointer/object.
Also, you never have to check if new returns NULL, because it never will return NULL. It will throw an exception if it could not create an object.
I hate the amount of code checking for nulls adds, so I only do it for functions I export to another person.
If use the function internally, and I know how I use it, I don't check for nulls since it would get the code too messy.
the answer is yes, if you are not in control of the object. that is, if the object is returned from some method you do not control, or if in your own code you expect (or it is possible) that an object can be null.
it also depends on where the code will run. if you are writing professional code that customers / users will see, it's generally bad for them to see null pointer problems. it's better if you can detect it beforehand and print out some debugging information or otherwise report it to them in a "nicer" way.
if it's just code you are using informally, you will probably be able to understand the source of the null pointer without any additional information.
I figure I can do a whole lot of checks for NULL pointers for the cost of (debugging) just one segfault.
And the performance hit is negligible. TWO INSTRUCTIONS. Test for register == zero, branch if test succeeds. Depending on the machine, maybe only ONE instruction, if the register load sets the condition codes (and some do).
Others (AshleysBrain and Neil Butterworth), already answered correctly, but I will summarize it here:
Use references as much as possible
If using pointers, initialize them either to NULL or to a valid memory address/object
If using pointers, always verify if they are NULL before using them
Use references (again)... This is C++, not C.
Still, there is one corner case where a reference can be invalid/NULL :
void foo(T & t)
{
t.blah() ;
}
void bar()
{
T * t = NULL ;
foo(*t) ;
}
The compiler will probably compile this, and then, at execution, the code will crash at the t.blah() line (if T::blah() uses this one way or another).
Still, this is cheating/sabotage : The writer of the bar() function dereferenced t without verifying t was NOT null. So, even if the crash happens in foo(), the error is in the code of bar(), and the writer of bar() is responsible.
So, yes, use references as much as possible, know this corner case, and don't bother to protect against sabotaged references...
And if you really need to use a pointer in C++, unless you are 100% sure the pointer is not NULL (some functions guarantee that kind of thing), then always test the pointer.
I think that is a good idea for a debug version.
In a release version, checking for null pointers can result in a performance degradation.
Moreover, there are cases where you can check the pointer value in a parent function and avoid the checking in its children.
If the pointers are coming to you as parameters to a function, then make sure they are valid at the beginning of the function. Otherwise, there is not much point. new throws an exception on failure.