What is the behavior of calling a null function pointer?
void (*pFunc)(void) = NULL;
pFunc();
Why is it advisable to initialize yet unused function pointers to NULL?
In C and C++, this is called undefined behaviour, meaning that this can lead to a Segmentation fault, nothing or whatever such a case will cause based on your compiler, the operating system you're running this code on, the environment (etc...) means.
Initializing a pointer to a function, or a pointer in general to NULL helps some developers to make sure their pointer is uninitialized and not equal to a random value, thereby preventing them of dereferencing it by accident.
What happnes when u try to access NULL?
Following is true about data as well as code, and this is what
happens when you try to read NULL(or any address from 0 to
4096,i.e atleast first page of segment). Root cause of this lies in
OS and microprocessor segmentation/paging architecture
When you try to access NULL( or 0) address, in any of data or code
section, it causes segmentation fault(which is actually a killer
page fault). First page of section is treated as out of( or invalid
part of) virtual address space. That is purposefully that first page
is kept invalid( or not present) so atleast one address that pointer
contains could be represented as invalid in program at execution
time.
Page descriptor of the 1st page(which contains virtual address 0,
NULL), has first bit "present" as 0 (means its invalid page). Now if
you try to access NULL pointer(0 address) it will cause to raise a
page fault as page is not present, and OS will try to handle this
page fault. When page fault handler see that its trying to access
1st page, which is treated as a invalid part of virtual address
space it kills the process. This is all about user space process. If
you try to access NULL pointer in system process(kernel level code),
it will fail your OS an crash the system.
Links: http://en.wikipedia.org/wiki/Page_fault#Invalid
http://en.wikipedia.org/wiki/Memory_protection#Paged_virtual_memory
http://pdos.csail.mit.edu/6.828/2005/readings/i386/s05_02.htm
Above is sufficient bt as i think u should read this as well
http://www.iecc.com/linker/linker04.txt
Why function pointer is initialized to NULL?
Although if you try to call the with NULL its going to give page/segment fault. NULL signifies its invalid function. If it
contains any garbage address but in valid virtual address space of
code section, i think any code at that address will be called, which
could be even more disaster(spl in case of real time systems).
Initialize funcp = funct_foo_name + 1; now call function using
function pointer. Function pointer points to valid virtual address
space of code section. bt function will start from incorrect place
to execute. which could result into wrong code execution or wrong
order.
It's advisable for the same reason as initializating "normal" (data) pointers to NULL: because it potentially makes some errors easier to track down. Opinions on whether this is useful or not of course vary :-)
Related
I've created a class, say I named it MyClass, as well as another that inherits from it, say MyClassDaughter then I tried the following:
MyClassDaughter *MyClassDaughterPointer;
vector <MyClass*> MyClassVector;
MyClassVector.push_back(MyClassDaughterPointer);
MyClassVector[0]->SetSomethingInMyClassDaughter;
When I try to run the executable it says "Segmentation Violation".
(I think must say that my code has some Root stuff in it... Could that be the problem? Anyways, I know that, usually, segmentation violation errors are cause by trying to access memory that we don't have permission to access, but I think I do have permission to access this memory. Am I wrong?)
You do not initialize MyClassDaughterPointer, so you push some random (wild) pointer to the vector.
You need to create new instance of MyClassDaughterPointer. Assuming you have a default constructor, it will look like this:
MyClassDaughter *MyClassDaughterPointer = new MyClassDaughterPointer();
The pointer
MyClassDaughter *MyClassDaughterPointer;
Was never set to anything but there is some uninitialized content if that was on the stack or just null is that was static. Therefore you cannot try to access it as you do, that causes Undefined Behavior.
MyClassVector[0]->SetSomethingInMyClassDaughter; // that is same pointer set in vector entry
Unsure what compiler does as long as it usually has such code to be optimized out and that should not have any effect - no job for CPU here at all as long as that pointer is not used. But debug mode is right always attempting to load the address to some register.
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.
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.
Unhandled exception at 0x523d14cf (msvcr100d.dll) in IntellitracTCPIP.exe: 0xC0000005: Access violation reading location 0x00000008.
what can cause this error? and how to solve it
The address you're attempting to read suggests that you have a struct consisting of a number of 4-byte integers. You have a pointer to that struct type, but that pointer is null. Your program wants to read the third one — the offset of the third integer field would be 8. Add that to the null-pointer address 0, and you get 0x00000008. (It could be a struct of smaller or larger types, or even an array, but my experience tells me 4-byte integers is most likely.)
The error message indicates that the offending line of code belongs to msvcr100d.dll. That's not your code; you have probably passed a null pointer to some C run-time function. That function has assumed you provided a valid pointer and attempted to read the third field of the struct, but since that pointer is not valid, the OS intercepted the read attempt and threw an exception instead.
Find the last line of code in your program before that error occurs. To do that, you can use the call stack to see the chain of function calls that your program made to get to the point it crashed. Go down the list until you find one of your functions. Do you see any pointers? Can you guarantee that they're all valid when you call that function? If not, then are you sure you're supposed to call that function? Either make sure the pointer is valid, or avoid calling the function with null pointers.
0xC0000005: Access violation reading location 0x00000008.
This indicate a bad pointer. No pointers show point to such a low address as 0x00000008. You are not giving enough information on this, try running the program under a debugger.
My application is suspending on a line of code that appears to have nothing wrong with it, however my IDE appears to be suspending on that line with the error:
gdb/mi (24/03/09 13:36) (Exited. Signal 'SIGSEGV' received. Description: Segmentation fault.)
The line of code simply calls a method which has no code in it. Isn't a segmentation fault when you have a null reference? If so, how can an empty method have a null reference?
This piece of code, seems to be causing the issue:
#include <sys/socket.h>
#define BUFFER_SIZE 256
char *buffer;
buffer = (char*)GetSomePointer()->SomeStackMemoryString.c_str();
int writeResult = write(socketFD, buffer, BUFFER_SIZE);
bzero(buffer, BUFFER_SIZE);
int readResult = read(socketFD, buffer, BUFFER_SIZE);
When the line using the read(...) method is commented out, the problem goes away.
Update:
I have changed the question to point toward the actual problem, and I have removed all the irrelevant code - and I also answered my own question so that people reading this know specifically what the issue is, please read my answer before saying "you're a moron!".
First, calling a method through a null pointer or reference is strictly speaking undefined behaviour. But it may succeed unless the call is virtual.
Calling virtual methods virtually (through a pointer/reference, not from the derived class with Class::Method() way of invokation) always fails if the reference/pointer is null because virtual calls require access to vtable and accessing the vtable through a null pointer/reference is impossible. So you can't call an empty virtual method through a reference/pointer.
To understand this you need to know more about how code is organized. For every non-inlined method there's a section of code segment containing the machine code implementing the method.
When a call is done non-virtually (either from a derived class or a non-virtual method through a reference/pointer) the compiler knows exactly which method to call (no polymorphism). So it just inserts a call to an exact portion of code and passes this pointer as the first parameter there. In case of calling through null pointer this will be null too, but you don't care if your method is empty.
When a call is done virtually (through a reference/pointer) the compiler doesn't know which exactly method to call, it only knows that there's a table of virtual methods and the address of the table is stored in the object. In order to find what method to call it's necessary to first dereference the pointer/reference, get to the table, get the address of method from it and only then call the method. Reading the table is done in runtime, not during compilation. If the pointer/reference is null you get segmentation fault at this point.
This also explains why virtual calls can't be inlined. The compiler simply has no idea what code to inline when it's looking at the source during compilation.
Your code is bogus: buffer points to some random piece of memory. I'm not sure why the line with bzero is not failing.
The correct code is:
char buffer[BUFFER_SIZE];
bzero(buffer, BUFFER_SIZE);
int readResult = read(socketFD, buffer, BUFFER_SIZE);
or you can use calloc(1, BUFFER_SIZE) to get some memory allocated (and zeroed out).
Without code, the best I can do is a wild guess. But here goes:
Your "long-running code" is writing to an invalid pointer. (Either a totally random pointer, or going past the beginning/start of a buffer or array). This happens to be clobbering the virtual function table for your object - either it's overwriting the pointer to the object, or the vptr member of the object, or it's overwriting the actual global virtual function table for that class.
Some things to try:
Put a sentinel member in your class. E.g. an int which is initialised to a known pattern (0xdeadbeef or 0xcafebabe are common) in your constructor, and never changed. Before you make the virtual function call, check (assert()) that it still has the right value.
Try using a memory debugger. On Linux, options include Electric Fence (efence) or Valgrind.
Run your program under a debugger (gdb is fine) and poke around to see what's wrong - either post-mortem after the segfault happens, or by setting a breakpoint just before the place it's going to segfault.
I cannot think of any reason why an empty method on its own would cause such a problem. Without any other context, my first though would be that a problem elsewhere is corrupting your memory and it just so happens to manifest itself in this way here.
We had that kind of a problem before, and I wrote about it in this answer here. That same question has a lot of other good advice in it too which might help you.
Isn't a segmentation fault when you have a null reference?
Possibly, but not necessarily. What causes a segfault is somewhat platform-specific, but it basically means that your program is accessing memory that it shouldn't be. You might want to read the wikipedia article to get a better idea of what it is.
One thing you might check on, does the empty method have a return type? I could be wrong on this, but if it returns an object, I could see how a copy constructor can get called on garbage if the method isn't actually returning an object. This could cause all sorts of wonky behavior.
Do you get the same result if you change its return type to void or you return a value?
The issue is because the buffer variable is using unassigned memory, which causes memory corruption when the read(...) function puts data in buffer.
Normally, bzero would actually cause the segmentation fault, but because a string is being assigned to the memory location, the read function was allowed to write past the allocated memory (causing the leak).
/* this causes *some* memory to be allocated,
* tricking bzero(...) to not SIGSEGV */
buffer = (char*)GetSomePointer()->SomeStackMemoryString.c_str();
int writeResult = write(socketFD, buffer, BUFFER_SIZE);
This change solves the memory leak:
#define BUFFER_SIZE 256
// Use memory on the stack, for auto allocation and release.
char buffer[BUFFER_SIZE];
// Don't write to the buffer, just pass in the chars on their own.
string writeString = GetSomePointer()->SomeStackMemoryString;
int writeResult = write(socketFD, writeString.c_str(), writeString.length());
// It's now safe to use the buffer, as stack memory is used.
bzero(buffer, BUFFER_SIZE);
int readResult = read(socketFD, buffer, BUFFER_SIZE);
Are you calling the virtual method from the constructor of a base class? That could be the problem: If you're calling a pure virtual method from class Base in Base's constructor, and it is only actually defined in class Derived, you might end up accessing a vtable record that has not yet been set, because Derived's constructor has not been executed at that point.