This guy:
virtual phTreeClass* GetTreeClass() const { return (phTreeClass*)m_entity_class; }
When called, crashed the program with an access violation, even after a full recompile. All member functions and virtual member functions had correct memory addresses (I hovered mouse over the methods in debug mode), but this function had a bad memory address: 0xfffffffc.
Everything looked okay: the 'this' pointer, and everything works fine up until this function call. This function is also pretty old and I didn't change it for a long time. The problem just suddenly popped up after some work, which I commented all out to see what was doing it, without any success.
So I removed the virtual, compiled, and it works fine. I add virtual, compiled, and it still works fine! I basically changed nothing, and remember that I did do a full recompile earlier, and still had the error back then.
I wasn't able to reproduce the problem. But now it is back. I didn't change anything. Removing virtual fixes the problem.
Don't ever use C-style casts with polymorphic types unless you're seriously sure of what you're doing. The overwhelming probability is that you cast it to a type that it wasn't. If your pointers don't implicitly cast (because they cast to a base class, which is safe) then you're doing it wrong.
Compilers and linkers are pieces of software written by human like any other, and thus inherently cannot be error-free..
We occasionally run into such inexplicable issues and fixes too. There's a myth going around here that deleting the ncb file once fixed a build..
Given that recompiling originally fixed the problem, try doing a full clean and rebuild first.
If that fails, then it looks extremely likely that even though your this pointer appears correct to you, it is in fact deleted/deconstructed and pointed at garbage memory that just happens to look like the real object that was there before. If you're using gdb to debug, the first word at the object's pointer will be the vtable. If you do an x/16xw <addr> (for example) memory dump at that location gdb will tell you what sort of object's vtable resides there. If it's the parent-most type then the object is definitely gone.
Alternately if the this pointer isthe same every time you can put a breakpoint in the class destructor with the condition that this == known_addr.
Related
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.
If I come across old code that does if (!this) return; in an app, how severe a risk is this? Is it a dangerous ticking time bomb that requires an immediate app-wide search and destroy effort, or is it more like a code smell that can be quietly left in place?
I am not planning on writing code that does this, of course. Rather, I've recently discovered something in an old core library used by many pieces of our app.
Imagine a CLookupThingy class has a non-virtual CThingy *CLookupThingy::Lookup( name ) member function. Apparently one of the programmers back in those cowboy days encountered many crashes where NULL CLookupThingy *s were being passed from functions, and rather than fixing hundreds of call sites, he quietly fixed up Lookup():
CThingy *CLookupThingy::Lookup( name )
{
if (!this)
{
return NULL;
}
// else do the lookup code...
}
// now the above can be used like
CLookupThingy *GetLookup()
{
if (notReady()) return NULL;
// else etc...
}
CThingy *pFoo = GetLookup()->Lookup( "foo" ); // will set pFoo to NULL without crashing
I discovered this gem earlier this week, but now am conflicted as to whether I ought to fix it. This is in a core library used by all of our apps. Several of those apps have already been shipped to millions of customers, and it seems to be working fine; there are no crashes or other bugs from that code. Removing the if !this in the lookup function will mean fixing thousands of call sites that potentially pass NULL; inevitably some will be missed, introducing new bugs that will pop up randomly over the next year of development.
So I'm inclined to leave it alone, unless absolutely necessary.
Given that it is technically undefined behavior, how dangerous is if (!this) in practice? Is it worth man-weeks of labor to fix, or can MSVC and GCC be counted on to safely return?
Our app compiles on MSVC and GCC, and runs on Windows, Ubuntu, and MacOS. Portability to other platforms is irrelevant. The function in question is guaranteed to never be virtual.
Edit: The kind of objective answer I am looking for is something like
"Current versions of MSVC and GCC use an ABI where nonvirtual members are really statics with an implicit 'this' parameter; therefore they will safely branch into the function even if 'this' is NULL" or
"a forthcoming version of GCC will change the ABI so that even nonvirtual functions require loading a branch target from the class pointer" or
"the current GCC 4.5 has an inconsistent ABI where sometimes it compiles nonvirtual members as direct branches with an implicit parameter, and sometimes as class-offset function pointers."
The former means the code is stinky but unlikely to break; the second is something to test after a compiler upgrade; the latter requires immediate action even at high cost.
Clearly this is a latent bug waiting to happen, but right now I'm only concerned with mitigating risk on our specific compilers.
I would leave it alone. This might have been a deliberate choice as an old-fashioned version of the SafeNavigationOperator. As you say, in new code, I wouldn't recommend it, but for existing code, I'd leave it alone. If you do end up modifying it, I'd make sure that all calls to it are well-covered by tests.
Edit to add: you could choose to remove it only in debug versions of your code via:
CThingy *CLookupThingy::Lookup( name )
{
#if !defined(DEBUG)
if (!this)
{
return NULL;
}
#endif
// else do the lookup code...
}
Thus, it wouldn't break anything on production code, while giving you a chance to test it in debug mode.
Like all undefined behavior
if (!this)
{
return NULL;
}
this is a bomb waiting to go off. If it works with your current compilers, you are kind-of lucky, kind-of unlucky!
The next release of the same compilers might be more aggressive and see this as dead code. As this can never be null, the code can "safely" be removed.
I think it is better if you removed it!
If you have many GetLookup functions return NULL, then you're better off fixing code that calls methods using a NULL pointer. First, replace
if (!this) return NULL;
with
if (!this) {
// TODO(Crashworks): Replace this case with an assertion on July, 2012, once all callers are fixed.
printf("Please mail the following stack trace to myemailaddress. Thanks!");
print_stacktrace();
return NULL;
}
Now, carry on with your other work, but fix these as they roll in. Replace:
GetLookup(x)->Lookup(y)...
with
convert_to_proxy(GetLookup(x))->Lookup(y)...
Where conver_to_proxy does returns the pointer unchanged, unless it's NULL, in which case it returns a FailedLookupObject as in my other answer.
It may not crash in most compilers since non-virtual functions are typically either inlined or translated into non-member functions taking "this" as a parameter. However, the standard specifically says that calling a non-static member function outside the lifetime of the object is undefined, and the lifetime of an object is defined as beginning when memory for the object has been allocated and the constructor has completed, if it has non-trivial initialization.
The standard only makes an exception to this rule for calls made by the object itself during construction or destruction, but even then one must be careful because the behavior of virtual calls can differ from the behavior during the object's lifetime.
TL:DR: I'd kill it with fire, even if it will take a long time to clean up all the call sites.
Future versions of the compiler are likely to more aggressively optimize in cases of formally undefined behavior. I wouldn't worry about existing deployments (where you know the behavior the compiler actually implemented), but it should be fixed in the source code in case you ever use a different compiler or different version.
this is something that's called 'a smart and ugly hack'. note: smart != wise.
finding all the call sites without any refactoring tools should be easy enough; break GetLookup() somehow so it doesn't compile (e.g. change signature) so you can identify misusage statically. then add a function called DoLookup() which does what all this hacks are doing right now.
In this case I'd suggest removing the NULL check from the member function and create a non-member function
CThingy* SafeLookup(CLookupThing *lookupThing) {
if (lookupThing == NULL) {
return NULL;
} else {
return lookupThing->Lookup();
}
}
Then it should be easy enough to find every call to the Lookup member function and replace it with the safe non-member function.
If it's something that's bothering you today, it'll bother you a year from now. As you pointed out, changing it will almost certainly introduce some bugs -- but you can begin by retaining the return NULL functionality, add a bit of logging, let it run in the wild for a few weeks, and find how many times it even gets hit?
This is a "ticking bomb" only if you are pedantic about the wording of the specification. However, regardless, it is a terrible, ill-advised approach because it obscures a program error. For that reason alone, I would remove it, even if it means considerable work. It is not an immediate (or even middle-term) risk, but it just isn't a good approach.
Such error hiding behavior really isn't something you want to rely on, either. Imagine you rely on this behavior (i.e. it doesn't matter whether my objects are valid, it will work anyway!) and then, by some hazard, the compiler optimizes out the if statement in a particular case because it can prove that this is not a null pointer. That is a legitimate optimization not just for some hypothetical future compiler, but for very real, present-time compilers as well.
But of course, since your program isn't well-formed, it happens that at some point you pass it a null this around 20 corners. Bang, you're dead.
That's very contrieved, admittedly, and it won't happen, but you cannot be 100% certain that it still cannot possibly happen.
Note that when I shout out "remove!", that does not mean the whole lot of them must be removed immediately or in one massive manpower operation. You could remove these checks one by one as you encounter them (when you change something in the same file anyway, avoid recompilations), or just text-search for one (preferrably in a highly used function), and remove that one.
Since you are using GCC, you may be intersted in __builtin_return_address, which may help you remove these checks without massive manpower and totally disrupting the whole workflow and rendering the application entirely unusable.
Before removing the check, modify it to to output the caller's address, and addr2line will tell you the location in your source. That way, you should be able to quickly identify all the locations in the application that are behaving wrongly, so you can fix these.
So instead of
if(!this) return 0;
change one location at a time to something like:
if(!this) { __builtin_printf("!!! %p\n", __builtin_return_address(0)); return 0; }
That lets you identify the invalid call sites for this change while still letting the program "work as intended" (you can also query the caller's caller if needed). Fix every ill-behaved location, one by one. The program will still "work" as normal.
Once no more addresses come up, remove the check alltogether. You might still have to fix one or the other crash if you are unlucky (because it didn't show while you tested), but that should be a very rare thing to happen. In any case, it should prevent your co-worker from shouting at you.
Remove one or two checks per week, and eventually none will be left. Meanwhile, life goes on and nobody notices what you're doing at all.
TL;DR
As for "current versions of GCC", you are fine for non-virtual functions, but of course nobody can tell what a future version might do. I deem it however highly unlikely that a future version will cause your code to break. Not few existing projects have this kind of check (I remember we had literally hundreds of them in Code::Blocks code completion at some time, don't ask me why!). Compiler makers probably don't want to make dozens/hundreds of major project maintainers unhappy on purpose, only to prove a point.
Also, consider the last paragraph ("from a logical point of view"). Even if this check will crash and burn with a future compiler, it will crash and burn anyway.
The if(!this) return; statement is somewhat useless insofar as this cannot ever be a null pointer in a well-formed program (it means you called a member function on a null pointer). This does not mean, of course, that it couldn't possibly happen. But in this case, the program should crash hard or abort with an assertion. Under no conditions should such a program continue silently.
On the other hand, it is perfectly possible to call a member function on an invalid object that happens to be not null. Checking whether this is the null pointer obviously doesn't catch that case, but it is the exact same UB. So, apart from hiding wrong behavior, this check also only detects one half of the problematic cases.
If you are going by the wording of the speficication, using this (which includes checking whether it's a null pointer) is undefined behavior. Insofar, strictly speaking, it is a "time bomb". However, I would not reasonably deem that a problem, both from a practical point of view and from a logical one.
From a practical point of view, it doesn't really matter whether you read a pointer that is not valid as long as you do not dereference it. Yes, strictly to the letter, this is not allowed. Yes, in theory someone might build a CPU which will check invalid pointers when you load them, and fault. Alas, this isn't the case, if you're being real.
From a logical point of view, assuming that the check will blow up, it still isn't going to happen. For this statement to be executed, the member function must be called, and (virtual or not, inlined or not) is using an invalid this, which it makes available inside the function body. If one illegitimate use of this blows up, the other will, too. Thus, the check is being obsoleted because the program already crashes earlier.
n.b.: This check is very similar to the "safe delete idiom" which sets a pointer to nullptr after deleting it (using a macro or a templated safe_delete function). Presumably, this is "safe" because it doesn't crash deleting the same pointer twice. Some people even add a redundant if(!ptr) delete ptr;.
As you know, operator delete is guaranteed to be a no-op on a null pointer. Which means no more and no less than by setting a pointer to the null pointer, you have successfully eliminated the only chance to detect double deletion (which is a program error that needs to be fixed!). It is not any "safer", but it instead hides incorrect program behavior. If you delete an object twice, the program should crash hard.
You should either leave a deleted pointer alone, or, if you insist on tampering, set it to a non-null invalid pointer (such as the address of a special "invalid" global variable, or a magic value like -1 if you will -- but you should not try to cheat and hide the crash when it is to occur).
You can safely fix this today by returning a failed lookup object.
class CLookupThingy: public Interface {
// ...
}
class CFailedLookupThingy: public Interface {
public:
CThingy* Lookup(string const& name) {
return NULL;
}
operator bool() const { return false; } // So that GetLookup() can be tested in a condition.
} failed_lookup;
Interface *GetLookup() {
if (notReady())
return &failed_lookup;
// else etc...
}
This code still works:
CThingy *pFoo = GetLookup()->Lookup( "foo" ); // will set pFoo to NULL without crashing
It's my personal opinion that you should fail as early as possible to alert you to problems. In that case, I'd unceremoniously remove each and every occurrence of if(!this) I could find.
I have a class B that inherits the class A with some virtual functions. Class B also has a virtual function (foo) that seems to have no address. When i walk with the debugger it points that foo has 0x00000000 address and when i try to step in it will fail with access violation at 0x00000005. If i make that function not virtual the debugger steps in and will work fine until i reach a std::vector. There when i call push_back it will fail with the same access violation at address 0x000000005 while writing some stuff at address 0xabababab, and the call stack points to a mutex lock in insert function.
Note: I'm not using any other thread and the incremental linker will crash every time i compile. Only the full linker will successfully create the exe. The compiler is from Visual Studio 2008 pro and this problem started to occur when stripping out unused source files and source code.
Unfortunately i was unable to revert to the previous state, in order to spot the change that created this.
How can i detect the source of the problem, without reverting the entire project? Also has anyone encountered this kind of error, maybe it might the same cause.
You guess that the virtual table is broken, but that's unlikely, because vtables are usually stored in read-only memory.
I can think of two reasons for this behavior:
The object you are using has been deleted. It may work by chance if the memory where the object used to be, but fail miserably if it get overwritten.
The object you are using is not of dynamic type B. Maybe it is of type A or maybe of an unrelated type.
I have successfully tracked this kind of issues with printf debugging: Add a few lines with printf("XXX %p", this); in the constructor of B, the destructor, the virtual functions and the failing function, and you'll be able to deduce what is happening.
Yes, I know, printf debugging is not cool...
You are calling a virtual function on a null pointer. The compiler adds code that will use a hidden pointer in the object to locate what is the final overrider, and that operation is failing. When you change the function to non-virtual, the call is dispatched statically, but again, access to members fail as the this pointer is null.
You should check the validity of the object on which you are calling the method in your code.
I've got a strange problem here. Assume that I have a class with some virtual methods. Under a certain circumstances an instance of this class should call one of those methods. Most of the time no problems occur on that stage, but sometimes it turns out that virtual method cannot be called, because the pointer to that method is NULL (as shown in VS), so memory access violation exception occurs. How could that happen?
Application is pretty large and complicated, so I don't really know what low-level steps lead to this situation. Posting raw code wouldn't be useful.
UPD: Ok, I see that my presentation of the problem is rather indefinite, so schematically code looks like
void MyClass::FirstMethod() const { /* Do stuff */ }
void MyClass::SecondMethod() const
{
// This is where exception occurs,
// description of this method during runtime in VS looks like 0x000000
FirstMethod();
}
No constructors or destructors involved.
Heap corruption is a likely candidate. The v-table pointer in the object is vulnerable, it is usually the first field in the object. A buffer overflow for some kind of other object that happens to be adjacent to the object will wipe the v-table pointer. The call to a virtual method, often much later, will blow.
Another classic case is having a bad "this" pointer, usually NULL or a low value. That happens when the object reference on which you call the method is bad. The method will run as usual but blow up as soon as it tries to access a class member. Again, heap corruption or using a pointer that was deleted will cause this. Good luck debugging this; it is never easy.
Possibly you're calling the function (directly or indirectly) from a constructor of a base class which itself doesn't have that function.
Possibly there's a broken cast somewhere (such as a reinterpret_cast of a pointer when there's multiple inheritance involved) and you're looking at the vtable for the wrong class.
Possibly (but unlikely) you have somehow trashed the vtable.
Is the pointer to the function null just for this object, or for all other objects of the same type? If the former, then the vtable pointer is broken, and you're looking in the wrong place. If the latter, then the vtable itself is broken.
One scenario this could happen in is if you tried to call a pure virtual method in a destructor or constructor. At this point the virtual table pointer for the method may not be initialized causing a crash.
Is it possible the "this" pointer is getting deleted during SecondMethod's processing?
Another possibility is that SecondMethod is actually being called with an invalid pointer right up front, and that it just happens to work (by undefined behavior) up to the nested function call which then fails. If you're able to add print code, check to see if "this" and/or other pointers being used is something like 0xcdcdcdcd or 0xfdfdfdfd at various points during execution of those methods. Those values are (I believe) used by VS on memory alloc/dealloc, which may be why it works when compiled in debug mode.
What you are most likely seeing is a side-effect of the actual problem. Most likely heap or memory corruption, or referencing a previously freed object or null pointer.
If you can consistently have it crash at the same place and can figure out where the null pointer is being loaded from then I suggest using the debugger and put a breakpoint on 'write' at that memory location, once the breakpoint is trigerred then most likely you are viewing the code that has actually caused the corruption.
If memory access violation happens only when Studio fails to show method address, then it could be caused by missing debug information. You probably are debugging the code compiled with release (non-debug) compiler/linker flags.
Try to enable some debug info in C++ properties of project, rebuild and restart debugger. If it will help, you will see all normal traceable things like stack, variables etc.
If your this pointer is NULL, corruption is unlikely. Unless you're zeroing memory you shouldn't have.
You didn't say if you're debugging Debug (not optimized) or Release (optimized) build. Typically, in Release build optimizer will remove this pointer if it is not needed. So, if you're debugging optimized build, seeing this pointer as 0 doesn't mean anything. You have to rely on the deassembly to tell you what's going on. Try turning off optimization in your Release build if you cannot reproduce the problem in Debug build. When debugging optimized build, you're debugging assembly not C++.
If you're already debugging a non-optimized build, make sure you have a clean rebuild before spending too much time debugging corrupted images. Debug builds are typically linked incrementally and incremental linker are known to produce problems like this. If you're running Debug build with clean build and still couldn't figure out what went wrong, post the stack dump and more code. I'm sure we can help you figure it out.
We have been debugging a strange case for some days now, and have somewhat isolated the bug, but it still doesn't make any sense. Perhaps anyone here can give me a clue about what is going on.
The problem is an access violation that occur in a part of the code.
Basically we have something like this:
void aclass::somefunc() {
try {
erroneous_member_function(*someptr);
}
catch (AnException) {
}
}
void aclass::erroneous_member_function(const SomeObject& ref) {
// { //<--scope here error goes away
LargeObject obj = Singleton()->Object.someLargeObj; //<-remove this error goes away
//DummyDestruct dummy1//<-- this is not destroyed before the unreachable
throw AnException();
// } //<--end scope here error goes away
UnreachableClass unreachable; //<- remove this, and the error goes away
DummyDestruct dummy2; //<- destructor of this object is called!
}
While in the debugger it actually looks like it is destructing the UnreachableClass, and when I insert the DummyDestruct object this does not get destroyed before the strange destructor are called. So it is not seem like the destruction of the LargeObject is going awry.
All this is in the middle of production code, and it is very hard to isolate it to a small example.
My question is, does anyone have a clue about what is causing this, and what is happening? I have a quite full featured debugger available (Embarcadero RAD studio), but now I am not sure what to do with it.
Can anyone give me some advise on how to proceed?
Update:
I placed a DummyDestruct object beneath the throw clause, and placed a breakpoint in the destructor. The destructor for this object is entered (and its only us is in this piece of code).
With the information you have provided, and if everything is as you state, the only possible answer is a bug in the compiler/optimizer. Just add the extra scope with a comment (This is, again, if everything is exactly as you have stated).
Stuff like this sometimes happens due to writing through uninitialized pointers, out of bounds array access, etc. The point at which the error is caused may be quite removed from the place where it manifests. However, based on the symptoms you describe it seems to be localized in this function. Could the copy constructor of LargeObject be misbehaving? Is ref being used? Perhaps somePtr isn't pointing to a valid SomeObject. Is Singleton() returning a pointer to a valid object?
Compiler error is also a possibility, especially with aggressive optimization turned on. I would try to recreate the bug with no optimizations.
Time to practice my telepathic debugging skills:
My best guess is your application has a stack corruption bug. This can write junk over the call stack, which means the debugger is incorrectly reporting the function when you break, and it's not really in the destructor. Either that or you are incorrectly interpreting the debugger's information and the object really is being destructed correctly, but you don't know why!
If stack corruption is the case you're going to have a really tough time working out what the root cause is. This is why it's important to implement tonnes of diagnostics (eg. asserts) throughout your program so you can catch the stack corruption when it happens, rather than getting stuck on its weird side effects.
This might be a real long shot but I'm going to put it out there anyway...
You say you use borland - what version? And you say you see the error in a string - STL? Do you include winsock2 at all in your project?
The reason I ask is that I had a problem when using borland 6 (2002) and winsock - the header seemed to mess up the structure packing and meant different translation units had a different idea of the memory layout of std::string, depending on what headers were included by the translation unit, with predictably disastrous results.
Here's another wild guess, since you mentioned strings. I know of at least one implementation where (STL) string copying is done in a lazy manner (i.e., no actual copying of the string contents takes place until a change is made; the "copying" is done by simply having the target string object point to the same buffer as the source). In that particular implementation (GNU) there is a bug whereby excessive copying causes the reference counter (how many objects are using the same actual string memory after supposedly copying it) to roll over to 0, resulting in all sorts of mischief. I haven't encountered this bug myself, but have been told about it by someone who has. (I say this because one would think that the ref counter would be a 32 bit number and the chances of that ever rolling over are pretty slim, to say the least, so I may not be describing the problem properly.)