I'm getting a seg fault that I do not understand. I'm using the Wt library and doing some fancy things with signals (which I only mention because it has enabled me to attempt to debug this).
I'm getting a pointer to one of my widgets from a vector and trying to call a method on the object it points to. Gdb shows that the pointer resolves, and if I examine the object it points to, it is exactly the one I need to modify. In this instance, the widget is broadcasting to itself, so it is registered as both the broadcaster and the listener; therefore, I was also able to verify that the 'broadcaster' pointer and the 'listener' pointer are accessing the same object. They do!
However, even though I can see that the object exists, and is initialized, and is in fact the correct object, when I try to call a method on the object, I get an immediate seg fault. I've tried a few different methods (including a few boolean returns that don't modify the object). I've tried calling them through the broadcaster pointer and the listener pointer, again, just to try to debug.
The debugger doesn't even enter the object; the segfault occurs immediately on attempting to call a method.
Code!
/* listeners is a vector of pointers to widgets to whom the broadcasting widget
* is trying to signal.
*/
unsigned int num_listeners = listeners.size();
for (int w = 0; w < num_listeners; w++)
{
// Moldable is an abstraction of another widget type
Moldable* widget = listeners.at(w);
/* Because in this case, the broadcaster and the listener are one in the same,
* these two point to the same location in memory; this part works. I know, therefore,
* that the object has been instantiated, exists, and is happy, or we wouldn't
* have gotten to this point to begin with. I can also examine the fields with gdb
* and can verify that all of this is correct.
*/
Moldable* broadcaster_debug = broadcast->getBroadcaster();
/* setStyle is a method I created, and have tested in other instances and it
* works just fine; I've also used native Wt methods for testing this problem and
* they are also met with segfaults.
*/
widget->setStyle(new_style); // segfault goes here!
}
I have read since researching that storing pointers in vectors is not the greatest idea and I should look into boost::shared_ptr. That may be so, and I will look into it, but it doesn't explain why calling a method on an object known to exist causes a segfault. I'd like to understand why this is happening.
Thanks for any assistance.
Edit:
I have created a gist with the vector operations detailed because it was more code than would comfortably fit in the post.
https://gist.github.com/3111137
I have not shown the code where the widgets are created because it's a recursive algorithm and in order to do that, I would have to show the entire class decision tree for creating widgets. Suffice to say that the widgets are being created; I can see them on the page when viewing the application in a browser. Everything works fine until I start playing with my fancy signals.
Moar Edit:
When I take a look at the disassembly in instruction stepping mode, I can see that just before the segfault occurs, the following operation takes place, the first argument of which is listed as 'void'. Admittedly, I know nothing about Assembly much to my chagrin, but this seems to be important. Can anyone explain what this instruction means and whether it might be the cause of my woes?
add $0x378,%rax //$0x378 is listed as 'void'
Another Edit:
At someone's suggestion, I created a non-virtual method that I am able to successfully call just before the seg fault, meaning the object is in fact there. If I take the same method and make it virtual, the seg fault occurs. So, why do only virtual methods create a seg fault?
I've discovered now that if in the calling class, I make sure to specify Moldable::debug_test (and Moldable::setStyle), the seg fault does not take place. However, this seems to have a similar effect as const bubbling -- every virtual method seems to want this specifier. I've never witnessed this behaviour before. While i'm willing to correct my code if that's REALLY how it's supposed to be, I'm not sure if the root problem is something else.
Getting there!
Well, I figured out the problem, though I'm sad to say it was a totally newbish mistake that due to the nature of the project was super difficult to find. I'll put the answer here, and I've also voted to close the question as too localized. Please feel free to do the same.
The BroadcastMessage class had a __broadcaster field (Moldable* __broadcaster;). When passing in the pointer to the broadcaster into the BroadcastMessage constructor, I forgot to assign the inbound pointer to that field, meaning __broadcaster was not a fully realised instance of the Moldable class.
Therefore, some methods were in fact working -- those that could be inlined, or my dummy functions that I created for testing (one of which returned a value of 1, for instance), so it was appearing that there was a full object there when in fact there was not. It wasn't until calling a more specialized method that tried to access some specific, dynamic property of the object that the segfault occurred.
What's more, most of the broadcast message lifespan was in its constructor, meaning that most of its purpose was fulfilled without issue, because the broadcaster was available in the local scope of the constructor.
However, using Valgrind as suggested, I did uncover some other potential issues. I also pretty much stripped-down and re-built the entire project. I trashed tons of unnecessary code and it runs a lot faster now as a side effect.
Anyway, thanks for all the assistance. Sorry the solution wasn't more of a discovery.
Related
I have working code in a single class that looks like this
Mesh* player_; //
renderer_3d_->DrawSkinnedMesh(*player_, player_->bone_matrices());
seems straight forward, but I'm having trouble introducing another a vector of enemies going through classes, thanks to the pointers.
I have two extra classes, enemy and manager. Enemy contains a SkinnedMeshInstance, and manager should worry about drawing it.
Manager
std::vector <Enemy> enemy_;
enemy_.push_back(Enemy(*platform_)); // Initialise (platform is required by the default constructor, not relevant to the pointer issue)
rend->DrawSkinnedMesh(enemy_[0].getSkinnedMesh(), enemy_[0].getSkinnedMesh().bone_matrices()); //render, intellisense only accepts it this way
Enemy
Mesh* mesh_instance_;
Mesh getSkinnedMesh() { return *mesh_instance_; };
What am I doing wrong here? Notice how rendering has changed how it's dereferenced. This way doesn't work as it throws some illegal access errors either at 'return *mesh_instance_;' or deeper in the framework itself, depending on how I try to change the communication. Might be simple for some but I feel like I tried everything possible.
Solved. I didn't inisialise my pointer as NULL.
Dunde, I'd like to beg the indulgence of the group to pass along a couple of "lessons painfully learned" about code such as this excerpt:
Mesh getSkinnedMesh() { return *mesh_instance_; };
First, of course, you know that you need to be absolutely-certain that variables such as mesh_instance really are global, and that they really are initialized to NULL.
Now, since you know that a call to this "accessor function" is going to take place each and every time someone needs to "get a skinned mesh," you should always take full advantage of this opportunity. If you need to "automagically create a new object-instance," do so now. And (IMHO), if there's something that you can do to verify that the pointer-value is "good" (using a try construct to detect a runtime-error that occurs while doing so), do it. In this way, you now will be able to say: "if this method returns a value to you at all, then the value which it returns is good, because otherwise it's gonna blow up."
In practice, the hardest thing about any programming bug is – knowing that it exists, and where it is. "If you've got a traceback, you're home free."
Let me start off by saying I am VERY inexperienced with the workings of COM, but I have been tasked with debugging an issue for someone else
I have two COM projects named pvTaskCOM and pvFormsCOM and each has many Interfaces, but the two I am concerned with are:
ITaskActPtr which is in pvTaskCOM
IChartingObjectPtr which is in pvFormsCOM
The line of code causing my problem is:
ITaskActPtr pTaskAct = m_pChartObj;
Where m_pChartObj is an IChartingObjectPtr. The problem I was encountering was that pTaskAct was NULL after this assignment in one workflow, but fine in most other workflows. I dived into what is happening here using the debugger and found it is looking at the wrong COM entries during the QueryInterface. In the workflows that work fine, QueryInterface grabs entries from pvTaskCOM/pvTaskAct.h:
BEGIN_COM_MAP(CTaskAct)
COM_INTERFACE_ENTRY(ITaskAct)
.
.
.
END_COM_MAP()
Which contains the Interface I'm trying to cast to, and QueryInterface returns S_OK.
But in this other workflow m_pChartObj is instantiated in the same way, but QueryInterface for some strange reason looks inside pvFormsCOM/ChartingObject.h
BEGIN_COM_MAP(CChartingObject)
COM_INTERFACE_ENTRY(IChartingObject)
.
.
.
END_COM_MAP()
which does NOT contain the ITaskAct we are trying to cast to, and so QueryInterface returns E_NOINTERFACE.
The question I have is what could cause it to be looking at two different COM's for the same line of code? Is it some sort of inheritance issue? I just need a step in the right direction.
In the workflows that work fine, QueryInterface grabs entries from pvTaskCOM/pvTaskAct.h
It shouldn't be.
This line:
ITaskActPtr pTaskAct = m_pChartObj;
Is doing this under the hood:
ITaskAct *pTaskAct = NULL;
m_pChartObj->QueryInterface(IID_ITaskAct, (void*)&pTaskAct);
It is asking the IChartingObject's implementing object if it supports the ITaskAct interface, and if so to return a pointer to that implementation. So this code should only be looking at the entries of the COM_MAP for the CChartingObject class. It should not be looking at the CTaskAct class at all.
But in this other workflow m_pChartObj is instantiated in the same way, but QueryInterface for some strange reason looks inside pvFormsCOM/ChartingObject.h
That is the correct behavior, since that is where CChartingObject is actually implemented. If there is no entry for ITaskAct in the COM_MAP of CChartingObject, then the correct behavior is for CChartingObject::QueryInterface() to fail with an E_NOINTERFACE error.
So, the real problem is that your "working" workflows are actually flawed, and your "non working" workflow is doing the correct thing.
what could cause it to be looking at two different COM's for the same line of code? Is it some sort of inheritance issue?
No. The "working" workflows are corrupted, plain and simple. Calling QueryInterface() on an IChartingObject interface should be calling CChartingObject::QueryInterface(), but it is clearly calling CTaskAct::QueryInterface() instead. So either
the IChartingObject* pointer is actually pointing at a CTaskAct object instead of a CChartingObject object
something has corrupted memory and the IChartingObject's vtable is the unsuspecting victim.
I would suspect the former. So, in the "working" workflows, make sure the IChartingObject* pointer is actually pointing at the correct object. It sounds like someone took an ITaskAct* and type-casted it to a IChartingObject* without using QueryInterface(). Or they called QueryInterface() on some object and asked it for IID_ITaskAct instead of IID_IChartingObject but then saved the returned pointer in an IChartingObject* pointer instead of an ITaskAct* pointer.
You are probably getting a bit lost in the plumbing. This is C++ code that was meant to make COM a bit less draconian. An important aspect of COM is that client code only ever works with interfaces. It doesn't know anything about objects. An interface is a simple contract, a list of functions that you can call. IChartingObject would have, say, a Paint() function. ITaskAct would have, no real idea, something "tasky", a Schedule() function.
Note how m_pChartObj is a pretty misleading name. It stores an interface pointer, not an object. But not uncommon, it is easy to think of an interface pointer as an object pointer if the object implements only one interface or has a "dominant" interface that you'd use all the time. Hiding the object inside the server code is a very strong goal in COM, you can only ever make interface calls.
So the ITaskActPtr pTaskAct = m_pChartObj; basically announces, "I have a chart, I want to make task functions calls next". Like Schedule(). That requires COM to ask the chart object implementation "do you know anything about the task interface contract?". Inevitably it has to consult back to the server, in the interface map for the CChartingObject where IChartingObject came from, to see if it also implements ITaskAct.
So what you see happening is entirely normal. The answer is "no".
Background
I work with Watusimoto on the game Bitfighter. We use a variation of LuaWrapper to connect our c++ objects with Lua objects in the game. We also use a variation of Lua called lua-vec to speed up vector operations.
We have been working to solve a bug for some time that has eluded us. Random crashes will occur that suggest corrupt metatables. See here for Watusimoto's post on the issue. I'm not sure it is because of a corrupt metatable and have seen some really odd behavior about which I wish to ask here.
The Problem Manifestation
As an example, we create an object and add it to a level like this:
t = TextItem.new()
t:setText("hello")
levelgen:addItem(t)
However, the game will sometimes (not always) crash. With an error:
attempt to call missing or unknown method 'addItem' (a nil value)
Using a suggestion given in answer to Watusimoto's post mentioned above, I have changed the last line to the following:
local ok, res = pcall(function() levelgen:addItem(t) end)
if not ok then
local s = "Invalid levelgen value: "..tostring(levelgen).." "..type(levelgen).."\n"
for k, v in pairs(getmetatable(levelgen)) do
s = s.."meta "..tostring(k).." "..tostring(v).."\n"
end
error(res..s)
end
This prints out the metatable for levelgen if something when wrong calling a method from it.
However, and this is crazy, when it fails and prints out the metatable, the metatable is exactly how it should be (with the correct addItem call and everything). If I print the metatable for levelgen upon script load, and when it fails using pcall above, they are identical, every call and pointer to userdata is the same and as it should be.
It is as though the metatable for levelgen is spontaneously disappearing at random.
Would anyone have any idea what is going on?
Thank you
Note: This doesn't happen with only the levelgen object. For instance, it has happened on the TestItem object mentioned above as well. In fact, that same code crashes on my computer at the line levelgen:addItem(t) but crashes on another developer's computer with the line t:setText("hello") with the same error message missing or unknown method 'setText' (a nil value)
As with any mystery, you will need to peel it off layer by layer. I recommend going through the same steps Lua is going and trying to detect where the path taken diverge from your expectations:
What does getmetatable(levelgen).__index return? If it's a table, then check its content for addItem. If it's a function, then try to call it with (table, "addItem") and see what it returns.
Check if getmetatable returns reference to the same object before and after the call (or when it fails).
Are there several levels of metatable indirection that the call is going through? If so, try to follow the same path with explicit calls and see where the differences are.
Are you using weak keys that may cause values to disappear if there are no other references?
Can you provide a "default" value when you detect that it fails and continue to see if it "finds" this method again later? Or when it's broken, it's broken for every call after that?
What if you save a proper value for addItem and "fix" it when you detect it's broken?
What if you simply handle the error (as you do) and call it 10 times? Would it show valid results at least once (after it fails)? 100 times? If you keep calling the same method when it works, will it fail? This may help you to come up with a more reproducible error.
I'm not familiar with LuaWrapper to provide more specific questions, but these are the steps I'd take if I were you.
I strongly suspect the issue is that you have a class or struct similar to this:
struct Foo
{
Bar bar;
// Other fields follow
}
And that you've exposed both Foo and Bar to Lua via LuaWrapper. The important bit here is that bar is the first field on your Foo struct. Alternatively, you may have some class that inherits from some other base class and both the derived and base class are exposed to LuaWrapper.
LuaWrapper uses an function called an Identifier to uniquely track each object (like whether or not the given object has already been added to the Lua state). By default it uses the object address as a key. In cases like the one posed above it is possible that both Foo and Bar have the same address in memory, and thus LuaWrapper can get confused.
This may result in grabbing the wrong object's metatable when attempting to look up a method. Clearly, since it's looking at the wrong metatable it won't find the method you want, and so it will appear as if your metatable has mysteriously lost entries.
I've checked in a change that tracks each object's data per-type rather than in one giant pile. If you update your copy LuaWrapper to latest one from the repository I'm fairly certain your problem will be fixed.
After merging with upstream (commit 3c54015) LuaWrapper, this issue has disappeared. It appears to have been a bug in LuaWrapper.
Thanks Alex!
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.)
I'm working on a GUI in SDL. I've created a slave/master class that contains a std::list of pointers to it's own slaves to create a heirarchy in the GUI (window containing buttons. Button a label and so on). It worked fine for a good while, until I edited a completely different class that doesn't effect the slave/master class directly. The call to the list.push_front() in the old slave/master class now throws the following error when debugging in VS C++ 2008 express and I can't find what's causing it.
"Unhandled exception at 0x00b6decd in
workbench.exe: 0xC0000005: Access
violation reading location
0x00000004."
*workbench.exe is my project.
The exception is raised in the _Insert method in the list code on row 718:
_Nodeptr _Newnode = _Buynode(_Pnode, _Prevnode(_Pnode), _Val);
The list is created in the master/slave class' definition and the slave/master class is created on the heap to be inserted in another master's slave list. The list that crashes is empty when push_front() is called but it is second in line in the heirarchy, so it worked once. As I said, it worked fine before and the slave/master class hasn't been altered to cause the error.
The new class does use lists aswell. Can the use of several lists cause clashes? May I have accidentally screwed up the heap?
Any help and tips to what I could look for is appreciated.
P.S The code is rather large now so I would guess it's better to not include it. Especially since I'm not exactly sure just what causes the error. Sorry if it's a bit scarce
Update: I've replaced the push_front() with creating an iterator and using insert(). The result was an iterator pointing to "baadf00d" after assigning the list.begin(). baadf00d is some error/NULL pointer that VS uses to objects that haven't been assigned anything, as far as I can tell. I guess it's another sign that the list is corrupt?
Usually errors like this with addresses like 0x00000004 indicate dereferencing a NULL pointer, e.g.
struct point {
int x;
int y;
};
struct point *pt = NULL;
printf("%d\n", pt->y);
can create an error like that.
Doesn't smell like heap corruption to me, usually those errors tend to be subtler, I bet this is a case of a NULL pointer. I'd go up the call stack and hunt for null pointers, could be a member of the the object you're pushing on to the fron of the list or that object itself. If you do think this is a heap corruption issue, you can use gflags, which is free, to enable page heap and the like which will let you detect heap corruption earlier, hopefully as it happens, rather than by the side effects it causes later.
Probably, you have caused some kind of buffer overrun or other memory corruption in your original code which did not manifest until now. There is no risk of conflict between different list instances, and as you say, the new code does not interact with the old code. Therefore barring magic, you have coded a bug.
Given the lack of code, the best I can do is give you some scenarios I can think of:
The most obvious, and hardest to find, is a memory corruption. The list has been walked on, so adding to the item means the list manipulates crap memory.
You can test this by moving variables around in their declaration, and by changing the order of assignment. If this makes the error go away or move, you are looking at a memory problem. You could also try changing the list to a vector, and see what that does.
A second possibility is that you have a list of pointers/references and the items are being deallocated before/after being put on the stack. This can easily happen if you put the address of a stack object into a list allocated elsewhere. You say you created the object on the heap, so I guess it isn't this.
My guess, based on the seeing the combination of _Prevnode and push_front is that the list was corrupted earlier, possibly by misusing an iterator. Another way to corrupt a list is removing an element from an empty list. Make sure you have iterator debugging turned on in VS2008. It will catch many problems a lot earlier.
Finally after looking through every nook and cranny I've found the bug! It was completely unexpected and I feel a bit embarrassed about it.
I had recently re-arranged the files. Prior to that I had generic classes in one folder and my user interface files in a subfolder. I copied the GUI files to the main folder and I thought I linked everything up correctly, but obviously I missed one line and it never occurred to me when it started acting up. My library compiled since that was linked fine, but my testing program wasn't... it simply looked at the old header files! Worked fine to begin with ofcourse since the headers were the same, but then I edited one and the class declared in it started acting funny as mentioned, obviously, since it couldn't recognize the damn thing anymore. It looked like corrupted memory, so that's what I looked for.
Lesson learned: Don't keep two versions close to each other or at all.