尝试在函数内动态分配父指针给子指针会导致分段错误

Posted

技术标签:

【中文标题】尝试在函数内动态分配父指针给子指针会导致分段错误【英文标题】:Trying to dynamically allocate a parent pointer to a child inside a function is causing a segmentation fault 【发布时间】:2016-02-11 03:36:27 【问题描述】:

我一直在努力理解多态性和指针,但这个概念让我有些不知所措。幸运的是,我有 *** 和 google,所以我的大部分问题都可以轻松解决。但是,我已经尝试修复这个分段错误几个小时了,但没有运气,我不确定是什么问题。我已经剥离了所有内容以尝试了解出了什么问题,但我相信我缺少动态分配的核心概念。

我将一个字符指针传递给我的函数初始化,我不能在函数内动态分配它吗?我的代码可以编译,但在为(预期的)开关提供输入后,出现分段错误和核心转储。

但是,如果我排除函数初始化并仅在我的主函数中运行代码,则不会出现任何中断,并且 zed 会正确初始化为野蛮人类型。

#include "character.h"//abstract class
#include "barbarian.h"//inherits character



void initialize(character *object)//gets the values for the object
                              //and lets user deem which type of object
    int x=0;
    cout<< "1. Barbarian."<<endl;
    cout<< "2. Gollum."<<endl;
    cout<< "3. Baba Yaga."<<endl;
    cout<< "4. Blue Men Group."<<endl;
    cout<< "5. Unicorn."<<endl;
    while(!(cin>>x))
        cout<<"Input not valid."<<endl;
        cin.clear();
        cin.ignore(10000,'\n');
    
    cout<<"Input is: "<<x<<endl;               //debug line
    object = new barbarian("conan");           //seg fault here
    //down here is a switch that was excluded for this question
 

void die(character *kill)//is now kill
    delete kill;
               //this should delete the character after it is used

int main()
    srand(time(0));//used for roll functions in the parent class
    cout<<(-time(0))<<"seconds until 1970"<<endl;//debug makes sure srand is
                                            //doing what I want it to

    character* zed;  //zed = new barbarian("conan");//In main this works
    initialize(zed);
    //zed = new barbarian("conan"); This works
    (*zed).atkRoll();
    (*zed).defRoll();
    die(zed);

我希望能够传递一个字符指针,然后将它作为用户选择的类分配到堆上,并在 main 调用的其他函数中使用它。我认为可以只传递指针并将其作为函数中的参数。然后本地指针将指向与 main 中的指针相同的位置。当函数作用域关闭并且“对象”被删除时,main 中的指针应该保持指向野蛮人的内存位置。这无效吗?如果是这样,我能做些什么作为替代方案? 不告诉指针就不能在main中改变指针的类型吗?

我很困惑>.

【问题讨论】:

你需要传递一个指针指针。目前你只是传递一个指针的值,然后在你的初始化函数中覆盖该值的本地副本。 【参考方案1】:

我认为这应该是这样的:

void initialize(character **object)
    /* ... */
    *object = new barbarian("conan");

否则,您不会修改实际指针,而是修改它的临时副本。您需要将指针传递给指针。然后,在main()

character* zed;
initialize(&zed);

对上一段中问题的解释:

您在main() 中有character* zed。这意味着,一个包含地址的指针变量(还没有有意义的地址,只是垃圾):

zed = 0x12345678

现在您拨打initialize(zed)。在该函数中,有一个类型为“指向野蛮人的指针”的参数,称为object。它被初始化为zed的副本,即zed的值:

zed = 0x12345678
object = 0x12345678

现在您拨打object = new barbarian()。内存被分配,地址保存在object:

zed = 0x12345678
object = 0xABCDEF00

现在initialize() 退出。 object 是临时的并被销毁。剩下的:

zed = 0x12345678 (garbage)
object doesn't exist

修复在我的回答开头。

段错误应该发生在main(),而不是initialize(),我认为:

(*zed).atkRoll();
(*zed).defRoll();

因为您在未初始化的指向对象的指针上调用方法,这些对象(假定)尝试访问对象的字段。

还有:

void die(character **kill)
    delete *kill; *kill == nullptr;

尽管这种方法的想法对我来说看起来很糟糕。

【讨论】:

太棒了!这对我有用。我认为我感到困惑的地方在于,当我试图将对象分配给新的野蛮人时,我认为发生了分段错误。经过一番测试我发现这个错误其实是在函数关闭后发生的,zed仍然是未赋值的,我试图在它上面调用成员函数,程序很混乱。 哇,这绝对是一个绝妙的解释。你说我的删除方法的想法很糟糕,但是。为什么不好?在我的代码中,我打算创建多个需要删除的字符子实例。因为有更好的方法,所以有一个删除功能是不是很糟糕?我只是需要一些方法在程序结束时释放内存,这就是我能想到的。我对动态内存很陌生。 嗯,我第一次看到它是一个成员函数,现在我看到它是一个全局函数。然后或多或少都很好,但是,我只是将字符存储在容器或数组中,并在必要时删除整个数组(即程序退出/宇宙重新初始化等)我的意思是,包装@987654342 的意义何在@ 变成自己的整个方法? 你是对的。我实际上计划稍后使用一个数组,但首先我想确保我可以制作两个首先相互战斗的角色实例。然后我想将防御和攻击滚动功能划分为主要的战斗功能,然后将我的角色划分为阵列等等。不过我真的很想感谢你,你帮了很多忙!

以上是关于尝试在函数内动态分配父指针给子指针会导致分段错误的主要内容,如果未能解决你的问题,请参考以下文章

C ++释放共享库中动态分配的内存导致崩溃

构造一个指向 alloca 的函数指针会导致链接器错误?

默认构造函数的分段错误

为具有双指针的结构内的动态结构数组分配内存**

添加指向数组的指针时出现分段错误

为啥我的字符串分配会导致分段错误?