【问题标题】:Segmentation fault when accessing a list inside a struct访问结构内的列表时出现分段错误
【发布时间】:2011-04-02 08:30:28
【问题描述】:

我会尽量把事情说清楚。

这是我的结构:

struct scopeList{
       int id;
       list<int> internal_list;
};
typedef struct scopeList scopeList_T;

这是给我分段的代码。

int main(){
    scopeList_T* t1 = (scopeList_T*) malloc(sizeof(scopeList_T));
    t1->id = 5; //works fine
    t1->internal_list.push_front(5); //segmentation fault
} 

既然我正在分配内存并且访问 id 很好,为什么这会给我一个分段错误?我必须先对列表做一些特别的事情吗?

谢谢!

【问题讨论】:

    标签: c++ list struct malloc segmentation-fault


    【解决方案1】:

    使用new 而不是malloc

    sopeList_T* t1 = new scopeList_T;
    

    malloc 不运行任何构造函数。当您需要释放struct 时,请使用delete 而不是free - 您不能使用new 分配的free 对象(并且free 不会调用析构函数)。

    你也不需要那个 typedef,struct 声明就足够了。

    struct scopeList {
        int id;
        list<int> internal_list;
    };
    
    int main()
    {
        scopeList *t = new scopeList;
        ....
        delete t;
        ....
    }
    

    【讨论】:

    • 另请注意,使用delete 而不是free
    • 非常感谢,这真的很有帮助!看来我还在用 C 风格思考!
    • @Spap:实际上,使用newdelete 也是“C 风格”(!)。对于 C++ 代码风格,使用专门的容器、智能指针或简单地将其设为局部变量。
    • @ybungalobill:完全正确。如果您仍然使用 new 之类的东西,它必须是某个类型的构造函数的一部分,并在其析构函数中匹配 delete
    【解决方案2】:

    您没有使用构造函数初始化列表,因此将无效数据留在 internal_list 的位置。

    【讨论】:

      【解决方案3】:

      上面已经给出了正确的答案:您已经分配了结构的内存,但没有为处于未初始化状态的子对象运行任何构造函数。我必须坚持:这是绝对不行的。切勿将对 alloc & Co. 的调用与 C++ 代码混淆。

      【讨论】:

        【解决方案4】:

        由于malloc不调用构造函数,你必须做这两种方式之一:

        1. 使用new分配内存以及构造对象:

          sopeList_T* t1 = new scopeList_T;//it allocates and then call the ctor!
          
          //use delete to deallocate the memory
          delete t1;
          
        2. 或者使用malloc分配你已经在做的内存,并使用placementnew构造对象:

          scopeList_T* t1 = (scopeList_T*) malloc(sizeof(scopeList_T)); //allocation
          t1 = new (t1) scopeList_T; //it calls the ctor 
          
          //use free to deallocate the memory
          t1->~scopeList_T(); //call the destructor explicitly - necessary!
          free(t1);
          

        【讨论】:

          【解决方案5】:

          分配内存是不够的。 您还必须调用构造函数。

          在 C++ 中最常用和推荐的简单动态分配方式是

          scopeList_T* t1 = new scopeList_T;
          

          is 分配内存,然后调用构造函数。

          完成结构后,您必须像这样删除对象

          delete t1;
          

          添加:

          如果您真的需要使用其他内存分配器(例如 malloc/free 或您自己设计的东西),那么您必须分配内存并调用新的位置(就像显式调用构造函数一样)。完成对象后,您必须显式调用析构函数,然后释放内存。重要的是:为对象分配的内存必须满足此对象类型的对齐要求。

          例子:

          // allocating memory
          void* p = my_alloc( sizeof(scopeList_T) );
          
          if( p == NULL )
          {
          // report allocation error and throw or return
          }
          
          // placement new operator
          scopeList_T* t1 = new(p) scopeList_T; // t1 == p
          
          // do some thing with the object
          // .............................
          
          // call destructor explicitly
          t1->~scopeList_T();
          // free memory
          my_free(p); // or free(t1); that is the same
          

          【讨论】:

            猜你喜欢
            • 2014-05-31
            • 1970-01-01
            • 2020-12-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-05-14
            • 2020-02-06
            相关资源
            最近更新 更多