c++ - 为什么在使用 std::map::insert() 时编译顺序有时会导致段错误?

标签 c++ segmentation-fault stdmap

我有一个类叫做 Controller ,在其中,我有一个名为 Button 的类. Controller包含几个 Button不同类型的实例(例如 button_type_abutton_type_b )。


controller.h

#ifndef __controller__
#define __controller__
class Controller
{
public:
    class Button
    {
    public:
        Button(int type = -1);

    private:
        int type;
    };

    Controller();

    Button A;
    Button B;
    Button X;
    Button Y;
};
#endif


按钮类型为 int s,我希望能够关联某些按钮类型 int s 指向 Button这些特定类型的实例。

为了跟踪这个关联,我使用了 std::map<int, Controller::Button*> ,我typedefbuttonmap_t .

当我创建新的 Button实例(在 Controller 构造函数中), Button构造函数注册那些 Button 的类型附上 map 。


Controller .cpp

#include "controller.h"
#include <map>

typedef std::map<int, Controller::Button*> buttonmap_t;
buttonmap_t map;

Controller::Controller() :
A(0),
B(1),
X(2),
Y(3)
{ }

Controller::Button::Button(int type) :
type(type)
{
    map[type] = this;
}


然后我创建一个全局 Controller对象,我定义了 main() .


main.cpp

#include <iostream>
#include "controller.h"

Controller controller;

int main(int argc, const char * argv[])
{
    std::cout << "running..." << std::endl;
    return 0;
}


根据我编译源代码的顺序,程序要么运行良好,要么触发段错误:

apogee:MapTest$ gcc controller.cpp main.cpp -o maptest -lstdc++
apogee:MapTest$ ./maptest 
running...

apogee:MapTest$ gcc main.cpp controller.cpp -o maptest -lstdc++
apogee:MapTest$ ./maptest 
Segmentation fault: 11


似乎后一种情况是在正确初始化之前尝试使用 map ,这会导致段错误。当我使用 Xcode 进行调试时,调试器在“__tree”中停止为 std::map正在调用 __insert_node_at() , 抛出 EXC_BAD_ACCESS(code=1, address=0x0) .调用堆栈显示这是由第一个 Button 触发的实例调用 map[type] = this; .

那么,这是我的多部分问题:

  1. 为什么编译顺序会导致这种情况发生?
  2. 有没有办法实现这种intButton*不受影响的映射 编译顺序?
  3. 如果是,那是什么?

理想情况下,我仍然希望拥有所有 Controller - 和 Button - 单独 Controller 中的相关代码。*文件。


这似乎与以下问题有些相关(但不完全相同):

  1. Segmentation fault in std::map::insert(...)
  2. [] operator in std::map is giving me segmentation fault

最佳答案

当你有多个全局构造函数时,它们的执行顺序是不确定的。如果 controller 对象在 map 对象之前实例化, Controller 将无法访问该映射,从而导致段错误。但是,如果 map 对象首先被实例化,那么 Controller 就可以很好地访问它。

在这种情况下,它似乎是它们在命令行中出现的顺序。这就是为什么将 main.cpp 放在第一位会导致段错误 - controller 对象首先被实例化。

我建议将实例化移动到您的 main 中,因为这样您就可以准确地控制对象的实例化方式和顺序。

关于c++ - 为什么在使用 std::map::insert() 时编译顺序有时会导致段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17623815/

相关文章:

c++头文件相互包含

c++ - 为什么这个文件名参数是字符指针而不是字符串?

c - 尝试扫描字符串时如何修复段错误?

c++ - map 迭代器删除不调用适当的析构函数

c++ - 使用 std::map::extract 修改键

c++ - C++11 中的线程池

c++ - 是否可以列出所有可以通过 `.Call()` 加载的可用名称? .Call ("function"错误)

c++ - 如果我尝试将未压缩的 filtering_istream 复制到 stringstream 会崩溃

c - 段错误合并排序程序

python - 如何使用 Boost.Python 使用带有 std::map 或 std::vector 参数的构造函数来包装 C++ 类?