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

2022-01-12 00:00:00 pointers segmentation-fault c++

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

I've been working on understanding polymorphism and pointers and the concept somewhat escapes me. Luckily I have stackoverflow and google so most of my problems can be easily answered. However I've been trying to fix this segmentation fault for a few hours now with no luck and i'm uncertain as to what is breaking. I've stripped down everything to try and understand what's going wrong but I believe i'm missing a core concept in dynamic allocation.

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

I pass a character pointer into my function initialize, can I not dynamically allocate it inside a function? My code compiles but after giving an input for the (intended) switch there is a segmentation fault and the core dumps.

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

However if I exclude the function initialize and just run the code in my main function nothing breaks and zed is properly initialized to a barbarian type.

#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,'
');
    }
    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中改变指针的类型吗?

I want to be able to pass a character pointer and then allocate it on heap as a class of the users's choice and use it in other functions called by main. I thought it would be possible to just pass the pointer and the take it as a parameter in the function. Then the local pointer would point to the same place as the pointer in main. As the function scope closes and the "object" is deleted then the pointer in main should remain pointing to the memory location for a barbarian. Is this not valid? What can I do as an alternative if so? Can I not change the type of the pointer in main without telling the pointer?

我很困惑>.<

推荐答案

我觉得应该是这样的:

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

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

Since otherwise you're not modifying the actual pointer, but the temporary copy of it. You need to pass a pointer to a pointer instead. Then, in main():

character* zed;
initialize(&zed);

对上一段中问题的解释:

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

You have character* zed in main(). That means, a pointer variable that contains an address (no meaningful address yet, just garbage):

zed = 0x12345678

现在你调用 initialize(zed).在该函数中,有一个名为object 的指向野蛮人的指针"类型的参数.它被初始化为 zed 的副本,即 zed 的值:

Now you call initialize(zed). In that function, there is a parameter of type "pointer to barbarian" called object. It's initialized to a copy of zed, i.e. to the value of zed:

zed = 0x12345678
object = 0x12345678

现在你调用 object = new barbarian().分配内存并将地址保存在 object 中:

Now you call object = new barbarian(). Memory gets allocated and the address saved in object:

zed = 0x12345678
object = 0xABCDEF00

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

Now initialize() exits. object is temporary and gets destroyed. What remains:

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

修复在我的回答开头.

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

The segfault should occur here in main(), not in initialize(), I think:

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

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

Because you call methods on uninitialized pointers to objects that (supposedly) try to access the objects' fields.

还有:

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

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

Though the idea of this methods looks very bad to me anyway.

相关文章