【问题标题】:Segmentation Fault when Assigning Pointer分配指针时出现分段错误
【发布时间】:2020-02-18 01:51:43
【问题描述】:

当我尝试初始化一个具有指向其他类对象的类指针变量的类时,我得到分段错误。下面是示例代码sn-p。

我尝试先使用“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 app 而不是Application* app 创建Application,它似乎已经修复了它。但仍然:有人可以解释为什么这有效而使用指针无效吗?

【问题讨论】:

  • Application::run() 中它自己调用它,Network network(this)
  • 你问为什么在main() 中分配它而不是在Network 中分配它?
  • 我很困惑为什么我必须在 main() 中使用new,或者它可以只是没有指针的Application
  • @Ash 你应该很少需要newApplication app; 是干净的解决方案,Application 中的 sf::RenderWindow* window; 也是如此,应该是 sf::RenderWindow window;。而Network 的构造函数中的两个new 不应该存在。我不明白为什么Network 首先有一个指向sf::RenderWindow 的指针,而这可以通过application 访问。
  • 指针之类的东西是我永远无法理解的一个东西。谢谢大家的帮助!

标签: c++ pointers initialization sfml


【解决方案1】:

回答您的编辑,两者的区别

Application* app;

Application app;

是什么被分配和构造,什么没有。

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

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


我想添加另一条信息。在第一个例子中,指针不是对象,也没有要调用的构造函数,所以如果你不给它们赋值,它们的初始值基本上是随机的——无论当时在堆栈中。因此,您的指针不仅没有指向 Application,甚至可能没有指向可用的内存位置,这就是您遇到分段错误的原因。

【讨论】:

  • 技术唠叨:没有堆栈,C++ 非常快乐。如果你知道怎么做,你可以用仙尘实现自动数据存储。
  • 指针不是对象”:从技术上讲,指针在 C++ 中也被视为对象。然而,它们是非类类型的对象,所以你是对的,它们的默认初始化值是不确定的。
  • 在 C++ 中list what isn't an object 比对象更容易。令人恼火的是,同一个词有两种不同的用法。
  • 指针不是传统 OOP 意义上的对象,这似乎比 C++ 对象更理性。
【解决方案2】:

问题出在你的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();
}

【讨论】:

  • 只是更改了我发现的问题,很抱歉浪费您的时间提供更好的解决方案。你介意我问为什么我不能通过指针分配它吗? new 和普通的 Application 有什么区别?
猜你喜欢
  • 1970-01-01
  • 2018-07-20
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-08
相关资源
最近更新 更多