分配指针时出现段故障

问题描述 投票:0回答:2

[当我尝试初始化一个具有指向其他类对象的类指针变量的类时,出现了分段错误。下面的示例代码段。

我曾尝试使用'new'关键字将变量初始化为空类,然后在分配之前手动使用malloc进行初始化,并尝试仅在没有任何花哨分配的情况下分配变量,但没有任何效果。

// Caller
void Application::run()
{
    Network network(this);
    network.start();
}

// Seg fault here, at the line that assigns window
Network::Network(Application *app)
{
    application = new Application();
    window = new sf::RenderWindow();
        application = app;
    window = app->window;
}

// Header for Network
class Network 
{
    public:
        Application* application;
        sf::RenderWindow* window;
    // Functions
    Network(Application *app);
        void start();
        void networkLoop();
    private:
    protected:
};

// Header for Application
class Application 
{
    public:
    sf::RenderWindow* window;
    Theme* theme;
    // Functions
    Application();
    void run();
    private:
    protected:
};

// Main
#include "application.h"
#include <X11/Xlib.h>

int main()
{
    XInitThreads();
    Application* app;
    app->run();
}

我在使用C ++方面还很陌生,所以请原谅我出现明显的内存错误。我曾尝试寻找解决方案,但没有找到任何有效的方法。我接受指向Application的指针作为构造函数的输入,因为我希望RenderWindow和Application的相同实例可以保存在其他对象中。

编辑:我真的很傻,但是我更改了main(),用Application而不是Application app创建了Application* app,似乎已经解决了。但仍然:有人可以解释为什么这样做有效,而使用指针却不可行?

c++ pointers initialization sfml
2个回答
3
投票

为了回答您的编辑,两者之间的区别

Application* app;

Application app;

什么是分配和构造的,什么不是。

在第一个示例中,编译器在堆栈中预留了足够的空间来容纳指针,但没有为其可能指向的对象预留任何空间-您需要使用new手动进行此操作。这就是为什么程序无法正常工作的原因-您有一个指针空间,但是当您使用->取消引用该指针时,另一端没有Application等待。您告诉它找到Application并采用window属性并将其存储在其他位置,但从未创建window属性。

[在第二个示例中,编译器为完整的Application对象留出足够的空间,并为您调用构造函数。因此,当您这次取消引用指针时,会有Application等待在那里使用。


我想添加另一条信息。在第一个示例中,指针不是对象,也没有要调用的构造函数,因此,如果您不给它们分配值,则它们的初始值本质上是随机的-当时是堆栈中的任何值。因此,不仅您的指针没有指向Application,而且甚至没有指向可用的内存位置,这就是为什么出现分段错误的原因。


3
投票

问题出在您的main()

int main()
{
    XInitThreads();
    Application* app;
    app->run();
}

您需要在此处使用new并分配您的Application

int main()
{
    XInitThreads();
    Application* app = new Application(...);
    app->run();
}

但是,不要Network中进行。那会造成内存泄漏。改为执行此操作:

Network::Network(Application *app)
{
    application = app;
    window = app->window;
}

编辑:

有人可以解释为什么这行得通而使用指针行不通吗?

因此,指针本身不会分配任何内存。它们只是指针。他们持有地址。他们不会自行分配内存来允许这样的事情:

int a =0;
int *b = &a; // holds address of a

如果指针在此处分配数据,则可能导致内存泄漏或其他原因。因此,如果要保留一个独立于其他变量的新对象,则需要使用new或一些智能指针:

int* c = new int; // c holds an int independent of a or b

因此,如果您只是做这样的事情:

int* d;

d本身没有在其位置分配的内存。它是一个可以容纳任何地址的占位符。它可以保存现有地址,也可以保存新地址。但是它需要存储一些有效的地址,然后才能使用它。

[如果要创建Application的实例,则必须将其与new一起分配,或者如其他人所指出的,甚至根本不使用指针,这实际上是建议的操作步骤:] >

int main()
{
    XInitThreads();
    Application app;
    app.run();
}
© www.soinside.com 2019 - 2024. All rights reserved.