Checking if an C++ Pointer is valid (in Objective-C(++)) - c++

I've adapted Matt Gallagher's "Testing if an arbitrary pointer is a valid object pointer" in an iOS project which uses Objective-C++. It's working fine with Objective-C objects but it always tells me that my C++-Pointers are invalid regardless of whether it works or not. Sometimes the Code crashes at the pointer. Sometimes the code works fine. But the test-method always tells me the pointer is wrong.
Is here anybody who knows to adapt this code to C++ classes and objects too? I could imagine that the code is only working with Objective-C according to the use of "Class"

The contents of a pointer variable is either: A null pointer, a valid pointer to an object, a valid pointer to an array element or past the last element of an array, or some invalid pointer.
If it is an invalid pointer, then any attempt to use it invokes undefined behaviour. That includes any attempt to check that it is an invalid pointer. And there you are stuck. All you can do is check whether it is a null pointer, or whether it is equal to some other valid pointer.
You should go with the Objective-C philosophy: Trying to use an invalid pointer is a programming error. You don't try to detect and handle this at runtime. You let it crash and fix the bug in your code.

C++ pointers simply reference an address in memory. You could look at what's there in memory using a memory viewer tool, but that wouldn't even guarantee that the memory is still valid. For example:
char* test = new[13];
strcpy(test, "Hello World!");
delete[] test;
.
.
.
printf("%s", test);
In some cases this will print successfully. Sometimes it will print a garbage string. And sometimes it will segfault. There is nothing there to speak to the pointer's validity.
If you're looking at a program that has just segfaulted and you're trying to see what happened there are a few options available to you:
You can look at the memory through a memory viewer, that in combination with the line you faulted on can provide insight.
You can seed your memory before running to make this clearer use 0xbadfood5 or something similar.
Use Valgrind when running is a great tool, if you can deal with the overhead.
The best option is to do error checking in your code. It sounds like you don't have that or you wouldn't be here. Preconditions and postconditions are great and will save you a ton of time in the long run (like now.) However as a silver lining you should exploit this to exact better coding standards in your organization for the future.

Related

Nonsensical C++ and Objective-C++ crash on Mavericks

I've got a large Mac app that runs for a couple of days at a time operating on a large data set. It's a mix of Objective-C++ and C++. It runs great on Mountain Lion, but on Mavericks, after running for about 10 to 20 minutes (in which a couple of million objects are allocated and destroyed), it crashes. It behaves as if it's crashing with an invalid pointer (i.e. calling a function on a deleted C++ object), but the object it's pointing to is in a state that makes absolutely no sense.
All my C++ classes inherit from a common base class where the constructor looks something like this:
MyClass::MyClass()
{
mCreated = 12345; //int member variable set here and NEVER TOUCHED AGAIN.
//other initialization stuff
}
When it crashes, the debugger shows that in the bad object, the value for mCreated is 0. It's behaving as if the object never ran its constructor!
I don't think it's memory stomping, because this value is never anything other than 0 or its expected value, and none of the other fields in the object have values that look like the garbage you'd expect from memory stomping.
I've also tried running with scribble turned on, and the 0x555 and 0xaaa values don't show up anywhere. I've also tried Guard Edges.
In-depth investigation has not revealed anything. The bad object isn't even always the same class. All I can think of is that something with the new memory stuff in Mavericks (compressing unused memory) is causing some new behavior (maybe a bug or maybe some previously unknown, mostly-unenforced rule that now really matters).
Has anyone seen anything similar? Or does anyone know of any mostly-unknown memory rules that would apply more strongly under Mavericks?
I think you're right about the invalid pointer suspicion. It might be a pointer to a deleted object or it might be a garbage pointer. Either one would be consistent with the mCreated member being different than you expect. In the case of a deleted object, the memory could be used for something else and therefore set to some other value. In the case of a garbage pointer, you're not pointing to anything that ever was an instance of your class.
I don't know how well the Allocations instrument works for C++ objects, but you could try reproducing the crash under that. When it stops in the debugger, get the this pointer and then get the history of that address from Instruments.
If Instruments doesn't work, you can set the MallocStackLoggingNoCompact environment variable. Then, when it stops in the debugger, examine the this pointer and use the following commands to view the history of that address:
(lldb) script import lldb.macosx.heap
(lldb) malloc_info --stack-history 0x10010d680
(Use the this address instead of 0x10010d680, of course.)
Alternatively, you can use the malloc_history command from a shell to investigate the history, if doing it within LLDB is cumbersome.

C++ function used to work, now returning 0xfdfdfdfd

I have some code I wrote a few years ago. It has been working fine, but after a recent rebuild with some new, unrelated code elsewhere, it is no longer working. This is the code:
//myobject.h
...
inline CMapStringToOb* GetMap(void) {return (m_lpcMap);};
...
The above is accessed from the main app like so:
//otherclass.cpp
...
CMapStringToOb* lpcMap = static_cast<CMyObject*>(m_lpcBaseClass)->GetMap();
...
Like I said, this WAS working for a long time, but it's just decided to start failing as of our most recent build. I have debugged into this, and I am able to see that, in the code where the pointer is set, it is correctly setting the memory address to an actual value. I have even been able to step into the set function, write down the memory address, then move to this function, let it get 0xfdfdfdfd, and then manually get the memory address in the debugger. This causes the code to work. Now, from what I've read, 0xfdfdfdfd means guarding bytes or "no man's land", but I don't really understand what the implications of that are. Supposedly it also means an off by one error, but I don't understand how that could happen, if the code was working before.
I'm assuming from the Hungarian notation that you're using Visual Studio. Since you do know the address that holds the map pointer, start your program in the debugger and set a data breakpoint when that map pointer changes (the memory holding the map pointer, not the map pointed to). Then you'll find out exactly when it's getting overwritten.
0xfdfdfdfd typically implies that you have accessed memory that you weren't supposed to.
There is a good chance the memory was allocated and subsequently freed. So you're using freed memory.
static_cast can modify a pointer and you have an explicit cast to CMyObject and an implicit cast to CMapStringToOb. Check the validity of the pointer directly returned from GetMap().
Scenarios where "magic" happens almost always come back to memory corruption. I suspect that somewhere else in your code you've modified memory incorrectly, and it's resulting in this peculiar behavior. Try testing some different ways of entering this part of the code. Is the behavior consistent?
This could also be caused by an incorrectly built binary. Try cleaning and rebuilding your project.

How many bits to ignore when checking for NULL?

The following crashes with a seg-V:
// my code
int* ipt;
int bool set = false;
void Set(int* i) {
ASSERT(i);
ipt = i;
set = true;
}
int Get() {
return set ? *ipt : 0;
}
// code that I don't control.
struct S { int I, int J; }
int main() {
S* ip = NULL;
// code that, as a bug, forgets to set ip...
Set(&ip->J);
// gobs of code
return Get();
}
This is because while i is not NULL it still isn't valid. The same problem can happen if the calling code takes the address of an array index operation from a NULL pointer.
One solution to this is to trim the low order bits:
void Set(int* i) {
ASSERT((reinterpret_cast<size_t>(i))>>10);
ipt = i;
set = true;
}
But how many bits should/can I get rid of?
Edit, I'm not worried about undefined behavior as I'll be aborting (but more cleanly than a seg-v) on that case anyway.
FWIW: this is a semi-hypothetical situation. The bug that caused me to think of this was fixed before I posted, but I've run into it before and am thinking of how to work with it in the future.
Things that can be assumed for the sake of argument:
If Set is called with something that will seg-v, that's a bug
Set may be called by code that isn't my job to fix. (E.g. I file a bug)
Set may be called by code I'm trying to fix. (E.g. I'm adding sanity checks as part of my debuggin work.)
Get my be called in a way that provide no information about where Set was called. (I.e. allowing Get to seg-v isn't an effective way to debug anything.)
The code needn't be portable or catch 100% of bad pointers. It need only work on my current system often enough to let me find where things are going wrong.
There is no portable way to test for any invalid pointer except NULL. Evaluating &ip[3] gives undefined behaviour, before you do anything with it; the only solution is to test for NULL before doing any arithmetic on the pointer.
If you don't need portability, and don't need to guarantee that you catch all errors, then on most mainstream platforms you could check whether the address is within the first page of memory; it's common to define NULL to be address zero, and to reserve the first page to trap most null pointer dereferences. On a POSIX platform, this would look something like
static size_t page_size = sysconf(_SC_PAGESIZE);
assert(reinterpret_cast<intptr_t>(i) >= page_size);
But this isn't a complete solution. The only real solution is to fix whatever is abusing null pointers in the first place.
You shouldn't be doing pointer arithmetic (including array indexing) off of a null pointer at all.
And you should use 0, not NULL in c++. NULL is a feature of c, still supported but not idiomatic in c++.
In regards to the BCS's many comments and the edit. That changes the question from the rather naive one on the surface to a much deeper one. But...it is not going to be easy---in a language as permissive as c++---to protect yourself against people doing stupid things before calling your code.
Trying to work around undefined behavior will always be very dependant on your platform, compiler, version,etc. if it is at all possible.
Common *nixes never map the first page of the address space precisely to catch null pointer access, thus you might get away with checking if the pointer value is between 0 and 4096 (Or whatever page size your system uses).
But don't do this, you can't guard against everything that can go wrong, focus instead on getting the code right. If somone passes you an invalid pointer, chances are there's something gravely wrong anyway that a pointer validation check can't fix.
Is there any way you can exert some influence to get that bad code corrected? There is no possible way this can turn out well. Legally, just creating an invalid pointer is undefined behavior.
If Set is always going to be passed a small offset from ip, and ip will always be initialized to NULL, you are probably going to be OK with what you are doing. Most modern systems do have the null pointer constant as all bits zero, and most will do the natural thing. There is of course absolutely no guarantee that it will work on any given system with any given compiler and any given compiler options, and changing any of those might cause it to fail.
Since any use of bad pointers can cause program failure, you should consider what happens when the code triggers a memory violation.
Also, I don't know what your ASSERT macro does, but assert, in most implementations, is only activated in debug mode. If you want to push this piece of junk into production, or run in optimized mode, you might want to make sure it will still fail more gently.
If you don't mind a really bad hack, you can force a memory access with volatile (n.b. volatile is evil). According to the GCC docs, volatile accesses must be ordered across sequence points, so you can do something like this:
int test = *(volatile int *)i;
*(volatile int *)i = test;
I don't think = is a sequence point, but the following might also work:
*(volatile int *)i = *(volatile int *)i;
I really wouldn't recommend trying to work around a bug in somebody else's code. If you're not running everything you write through a debugger while you're developing code no amount of checks are going to help you catch all the problems. Get them to fix their code.
If you're not using a debugger, get a decent crash handler that dumps the callstack for each thread and as much additional information regarding the program state as possible. Try to figure out what could be going wrong from that.
Regularly running your code through static analysis tools can also help here.
Remember, that it might not be someone forgetting to initialise a pointer, it could be someone else overwriting that pointer through a bad memory write from somewhere completely unrelated. There are tools which can help track down such things too.
Regarding the NULL Vs 0 debate, #define NULL 0 is better for a couple of reasons:
1) You can more easily see when you're dealing with a pointer.
2) Using NULL offers no less or more safety than using 0. So why not make your code more readable?
3) When C++11 is finally released #define NULL nullptr is a lot easier to change than all those zeros. (You could go the other way and #define nullptr 0 today I suppose, but that will probably cause problems in the future if you're developing cross platform code.)
And for the record, the C++ standard explicitly states that a null pointer constant is an rvalue integer type that evaluates to zero. So please let's not have any more nonsense about null pointers not having to equal zero.
One reason, among many, you cannot do this in a portable fashion is that NULL is not guaranteed to be 0. It is only specified that null pointers will compare equal to 0. You may write a 0 (or the preprocessor macro "NULL") in your code, but the compiler knows that this 0 is in a pointer context so it generates the appropriate code to compare it to a null pointer, whatever the actual implementation of a null pointer is. See here and here for more information on that. Reinterpreting a NULL pointer as an integral type may cause it to have a true value instead of false.
You'd have to consider your particular operating system and hardware architecture. If you're only interested in detecting pointers that are "close to null" then you could use ASSERT(i > pageSize), assuming that the first page is always write protected in your OS.
But ... the obvious question is: Why bother? The OS will detect the null in this case and SEGV as you pointed out, which is just as good as an ASSERT, isn't it?

It is good programming practice to always check for null pointers before using an object in C++?

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.

problem with containers: *** glibc detected *** free(): invalid pointer: 0x41e0ce94 ***

I have a C++ program on Linux that crashes after some time with the message:
*** glibc detected *** free(): invalid pointer: 0x41e0ce94 ***
Inside the program I make extensive use of containers. They have to store objects of a simple class.
EDIT 2009-4-17:
In the meantime it seems clear that the error has nothing to do with the simple class. The error still occurs if I change the containers to hold other datatypes. The problem must be somewhere else in my code, I'm trying to figure it out at the moment...
Consider using a std::string to hold the string value instead of a raw char pointer. Then you won't have to worry about managing the string data in your assignment, copy, and destruction methods. Most likely your problem lies there.
Edit: There's no issue with the newer class you posted, and no problem with the first version if you're only using the char * to point to string constants. The problem lies elsewhere in the program or with the way you're using the class. You'll have to spend more time digging in the debugger and/or valgrind to track down the problem. I would figure out what is pointed to at the specified address and try determine why it's being freed twice.
At a guess, there is something wrong in your copy ctor, assignment op or destructor - you need to show the code for those.
Edit: Just noticed you don't have an assignment operator - assuming your copy constructor & destructor are OK, you need an assignment operator too, as the std:; containers will use it.
I have been fighting with a C/C++ application we are developing, and the first ideas that come to my mind are
A pointer has been modified and its pointing to an invalid possition (ptr++;) or something like that.
You have freed the object, but the pointer still holds the direction.
A tool like Valgrind may help you to detect possible errors in the code. To install:
sudo apt-get install valgrind
And to use it:
valgrind --tool=memcheck --leak-check=full ...
It will report errors while the program is running, and it will give you also a report after the program ends. The only problem is what valgrind identifies as a possible problem may not be a real problem. But it is an starting point.
It's most certainly a bad string value. Using std::string maybe help in this regard if it is a dangling pointer issue. Also ensure all the string initializations work as expected.
If I understand the class correctly, you assume that whatever memory resides at m_cstring won't be deallocated for the lifetime of the class. Which in your case also means for the lifetime of the containers. Check your scopes.
Another problem you may be encountering is if your Destructor is deleting the cstring then using a default value in the constructor is a really bad idea as you will be trying to deallocate a statically allocated cstring.
It is possible in C++ to define a function that is supposed to return a string, but doesn't return anything and you wind up with a bad string (Typically the compiler will catch the 'Reached end of non-void function', but not always).
Ditto on using valgrind.
As an addendum after reading various comments, there's always the possibility that a memory error somewhere else in the program corrupted one of the strings.
EDIT 4-16
At this point I would verify the values of the object are well formed on construct/destruct. (try printing them?) If everything looks good, you may have to look elsewhere in your code for the error.
What is inside your destructor? Probably it does free of the cstring. And If it is the case then you share your cstring pointer over instances and each instance then frees the same pointer.