Delphi Win32 编程/访问冲突问题

Asu*_*ine 5 delphi

我不完全确定如何命名它,所以提前道歉。

你看,我正在尝试使用 Delphi(我选择的语言)使用这个网站自学 Win32/DirectX 编程 - http://rastertek.com/tutindex.html

当然,该网站全部是用C++编写的,我必须将其移植到Delphi。乍一看,这似乎很简单。我正在学习 DirectX 11 的第二个教程 - 设置框架并显示初始窗口。

现在来说说我的实际问题。我收到访问冲突错误。所以我发现并开始使用 MadExcept 来尝试找出发生了什么。所以它告诉了我这些台词,但我对如何解决手头的问题一无所知。

我已将所有内容设置为模仿原始源代码。唯一真正的区别是,在指向变量类的指针的情况下,例如 m_input、m_grahics 和 system 的情况,我为它们创建了一个类型。所以我有 TSystemClass、TInputClass、TGraphicsClass,然后我有 PSystemClass 等,即 = ^TSystemClass 等。我认为这会让事情变得更简单、更整洁。顺便说一句,我认为应该这么说,但我为了构建复制构造函数而使初始类继承自 TPersistent,因此我可以使用它的分配过程。

那么,回到访问冲突错误。首先,问题出在系统类型为 PSystemClass 的主程序中。因此,出于我不知道的原因,当我尝试使用 system.create 时,就在那一刻,造成了访问冲突。然后我意识到我没有将系统分配给system.create。所以我尝试了这个,它说的是,我认为,在编译时出现一个错误,表明两者不兼容,因为 system.create 是 TSystemClass 类型,而 system 是 PSystemClass 类型。所以我尝试对其进行类型转换,并且成功了。但再一次,仍然遇到可怕的访问违规。

然后我有一个奇怪的想法,也许我应该直接从 TSystemClass 本身调用常规构造函数。我尝试过,需要再次打字。所以我做了。它成功了!不再出现访问冲突错误!现在...新问题!或者更确切地说,在这种情况下是“问题”。MadExcept 的调用堆栈中现在列出了 3 件事。第一个:

m_hinstance := GetModuleHandle(nil);
Run Code Online (Sandbox Code Playgroud)

据说这会导致访问冲突错误。但这到底是为什么呢?根据我的理解和阅读,如果 GetModuleHandle 设置为 null/nil,它应该检索调用它的文件的句柄,对吧?从文档的内容来看,它应该是可执行的。

但请注意:我不确定我是否有主程序、系统类内容、输入类内容和图形类内容,所有这些都在不同的程序/单元文件中以模仿原始源代码的性质。那么这可能是造成这种情况的原因吗?如果是这样我该如何解决它?将单元文件中的所有代码放入主程序文件中?不过,在我个人看来,这将是相当混乱和不直观的。

下一个更让我困惑。

InitializeWindows(ScreenWidth, ScreenHeight);
Run Code Online (Sandbox Code Playgroud)

除了注册窗口类并为窗口设置所有内容的函数之外,我不处理任何其他事情。所以我不太确定这里的问题是什么,因为它只处理 2 个参数,并且它们在调用之前就已经定义好了。所以我不太确定这里的问题是什么以及到底是什么导致了访问冲突。

最后最后一个是在主程序中:

return := system.initialize;
Run Code Online (Sandbox Code Playgroud)

Return 是我在原始源代码的 result 变量的所有实例中使用的,因为 result 当然是所有函数的内置变量。

我想如果系统永远无法正确执行它应该执行的操作,那么这里可能/应该发生一些事情。同样,因为我之前使用 TSystemClass.Create (类型转换为 PSystemClass)来创建系统,那么这会在这里做任何事情吗?这是否可能与另外两人有关,因为他们无法正确做好自己的事情?

最后一点;MadExcept 的调用堆栈上实际上还有最后一件事。

它在模块部分显示 Kernel32.dll,但除了主线程之外,它没有列出任何其他内容。(如果需要此信息,我很乐意提供)。

预先感谢阅读本文的任何人,我希望能找到有关此问题的一些帮助,以便我可以进一步学习。

Rob*_*edy 5

你实例化你的类都是错误的。这是来自的示例TSystemClass.Initialize

m_Input := PInputClass(m_Input.create);
Run Code Online (Sandbox Code Playgroud)

这是您声明为 的变量PInputClass

早些时候,TSystemClass.Create您在 中初始化了该变量:

m_Input := nil;
Run Code Online (Sandbox Code Playgroud)

因此,由于您有一个空引用,所以很明显您不能对其调用任何方法。特别是,您不能调用Create它。相反,调用Create您想要实例化的TInputClass.Create: 。

该构造函数返回您构造的类型的值,即 a TInputClass。它不返回 a PInputClass,因此您的类型转换是错误的。正如 Cosmin 的评论所解释的,Delphi 对象变量已经是指针。必须声明基于 Delphi 类的指针类型的情况极其罕见。正确的代码是这样的:

m_Input := TInputClass.Create;
Run Code Online (Sandbox Code Playgroud)

在该行之后,检查是否m_Input为空。在 Delphi 中你永远不必这样做;构造函数要么返回一个有效的对象,要么根本不返回。如果构造对象时出现问题,构造函数会抛出异常,并且赋值语句永远不会执行。(原始的 C++ 代码也犯了错误。new十多年来,该运算符都没有在失败时返回空指针,早在任何人能够开始编写 DirectX 11 教程之前。)

  • 我愚蠢地查看了这一点。道歉。但在那之后它现在可以工作了!尽管当按下转义键时我确实会抛出异常。虽然我可能会说,如果我无法弄清楚,那么是时候提出另一个问题了。非常感谢,罗布!你是一个真正的救星。天哪,你们工作得快吗?否则可能要花很长时间才能走到这一步~ (2认同)