我有std::map
我保存指向类的指针。在类的构造函数中传递了几个值,因此类中的变量具有实际值。我的问题是,当我调用该类的一个函数时,关键字this
会创建一个分段错误,该函数使用之前定义的变量之一。这看起来很详细(简短版):
Command::Command(const char *name, commandHandler h) // commandHandler is a function pointer
{
this->name = name;
this->handler = h;
}
Command::execute(int cn, std::vector<char *> args)
{
if (this->handler != NULL) // "this" is according to gdb a pointer to a class Command at 0x0
(handler)(cn, args);
}
地图位于静态类中,地图元素插入静态函数中。
编辑:由于评论和答案(谢谢你们):
我在函数registerCommands()中添加指向类的指针,它基本上使用Command *command_xxx = new Command("xxx", &(handler_func));
创建指针并将其放在静态类的映射中。该调用来自与map和registerCommands()函数在同一类中的另一个方法。使用commands.find("xxx")->second;
获取类指针,返回null - &gt;空指针。
答案 0 :(得分:2)
当您在设置为NULL
的指针上调用方法时,通常会发生这种情况。由于this
是传递给每个成员函数的隐藏参数,因此GDB将其显示为NULL
。例如:
Command *command = NULL;
command->execute(...);
答案 1 :(得分:2)
你有一个指向Command
的指针,但指针是0
。然后,此指针用于调用Command::execute
,这意味着使用this == 0
调用成员函数。
虽然它不符合标准,但您很可能会尝试添加代码来捕获它并打印一些可能有助于调试问题的信息:
if(!this) print_backtrace();
或类似的东西。 (有关Linux上的回溯,请参阅我之前提到的this answer)
答案 2 :(得分:2)
使用
commands.find("xxx")->second
获取类指针;返回null - &gt;空指针。
然后当你commands.find("xxx")->second->execute(...)
时,你会遇到段错误。这里至少有两件事是错的。
一个是->execute(...)
,而不检查找到的项是否为非空。如果找到的项为null,则调用未定义的行为。大多数系统会发生什么取决于execute()
是否为虚函数。如果它是虚拟的,您将在通话前收到段错误或总线错误。如果它是非虚拟的,则底层机器确切地知道要调用哪个函数。当您尝试访问数据成员时,会在execute()
函数内部发生段错误。您应该知道指针不为null,或者在调度对象调用之前检查它是否为空。一旦你完成->execute()
游戏结束,无论如何。
另一个问题是->second
。如果"xxx"
不在地图中怎么办?如果不是,commands.find("xxx")
将返回commands.end()
,并且对此进行操作是未定义的行为。所有你应该用结束迭代器测试你没有击中它。
它有点冗长,但你应该测试那些极端情况。您应该进行测试,即使经过艰苦的分析,您100%确信您的find
将始终返回入站迭代器,并且每个入站迭代器都具有非空映射值。您可以通过断言进行测试,最终可以将其关闭,但您应该始终进行测试。总是