map with string is broken?

2019-08-08 15:03发布

问题:

Yes. I can't see what I'm doing wrong.

The map is: string, int

Here's the method

bange::function::Add(lua_State *vm){  
 //userdata, function  
 if (!lua_isfunction(vm, 2)){  
  cout << "bange: AddFunction: First argument isn't a function." << endl;  
  return false;}  
 void *pfunction = const_cast<void *>(lua_topointer(vm, 2));  
 char key[32] = {0};  
 snprintf(key, 32, "%p", pfunction);  
 cout << "Key: " << key << endl;  
 string strkey = key;  
 if (this->functions.find(strkey) != this->functions.end()){  
     luaL_unref(vm, LUA_REGISTRYINDEX, this->functions[strkey]);}  
 this->functions[strkey] = luaL_ref(vm, LUA_REGISTRYINDEX);  
 return true;  

Ok, when the code is executed, It crashes and prints this output:

Program received signal SIGSEGV, Segmentation fault.  
0x00007ffff6e6caa9 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >
::compare(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const () from /usr/lib/libstdc++.so.6

Seriously, what's wrong with my code. Thanks for help.

Edit 1:

Ok, I've done the solution and still fails. I've tried directly inserting a string but it gives the same error.

Let's see, the object is a bange::scene inherited from bange::function. I create the object with lua_newuserdata:

bange::scene *scene = static_cast<bange::scene *>(lua_newuserdata(vm, sizeof(bange::scene)));
(...)
scene = new (scene) bange::scene(width, height, nlayers, vm);

I need this for Lua garbage collection. Now the access to bange::function::Add from Lua:

static int bangefunction_Add(lua_State *vm){
    //userdata, function
    bange::function *function = reinterpret_cast<bange::function *>(lua_touserdata(vm, 1));
    cout &lt&lt "object with bange::function: " &lt&lt function << endl;
    bool added = function->bange::function::Add(vm);
    lua_pushboolean(vm, static_cast<int>(added));
    return 1;
}

Userdata bange::scene is stored in Lua. Knowing that userdata scene is, in fact, the object's direction is the same when I've created the scene before. I need the reinterpret_cast, and then call the method. The pointer "this" is still the same direction inside the method.

solved

I did a small test in the bange::function constructor which works without problems.

bange::function::function(){  
    string test("test");  
    this->functions["test"] = 2;  
}  

I finally noticed that the problem is

bange::function *function = reinterpret_cast<bange::function *>(lua_touserdata(vm, 1));

because the object is bange::scene and no bange::function (I admit it, a pointer corruption) and this seems more a code design issue. So this, in a way, is solved. Thanks everybody.

回答1:

As strkey is the only string that you ever compare, it must be the source of the problems, and it originates from the char[] on the stack. I would start by getting rid of that.

std::stringstream str;
str << pfunction;
string strkey = str.str();

Of course, this error could also occur if you corrupted this, or really, if you just flat out corrupted the heap anywhere, anytime.



回答2:

There might be nothing wrong with this code.

A Segmentation fault happens when your code tries to read or write to memory that isn't mapped to your process. The point that it happens might not be related to where the bug is.

At some point in your program, before the segmentation fault, some code munged the heap. This could be

  1. Accessing a deleted/freed pointer
  2. Overwriting bounds of an array
  3. Casting an object to the wrong type and using it

None of these things has to crash immediately -- they could just silently corrupt memory. At some point later, when that memory is used, it might also not crash (just silently corrupt other memory). At some point you crash, but that point might be completely unrelated to the problem.

The strategy for debugging is to get the first corruption to crash. There are a few ways to do that.

  1. Use a debug heap. Here are some possibilities for GCC on Linux Debug heap/STL debugging equivalent for GCC?

  2. Valgrind: http://valgrind.org/