[当我尝试初始化一个具有指向其他类对象的类指针变量的类时,出现了分段错误。下面的示例代码段。
我曾尝试使用'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
,似乎已经解决了。但仍然:有人可以解释为什么这样做有效,而使用指针却不可行?
为了回答您的编辑,两者之间的区别
Application* app;
和
Application app;
什么是分配和构造的,什么不是。
在第一个示例中,编译器在堆栈中预留了足够的空间来容纳指针,但没有为其可能指向的对象预留任何空间-您需要使用new
手动进行此操作。这就是为什么程序无法正常工作的原因-您有一个指针空间,但是当您使用->
取消引用该指针时,另一端没有Application
等待。您告诉它找到Application
并采用window
属性并将其存储在其他位置,但从未创建window
属性。
[在第二个示例中,编译器为完整的Application
对象留出足够的空间,并为您调用构造函数。因此,当您这次取消引用指针时,会有Application
等待在那里使用。
我想添加另一条信息。在第一个示例中,指针不是对象,也没有要调用的构造函数,因此,如果您不给它们分配值,则它们的初始值本质上是随机的-当时是堆栈中的任何值。因此,不仅您的指针没有指向Application
,而且甚至没有指向可用的内存位置,这就是为什么出现分段错误的原因。
问题出在您的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();
}