Delphi Win32 编程/访问冲突问题

5

我不确定该怎么称呼这个问题,先提前道歉。

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

当然,这个网站全都是C++写的,所以我必须将其移植到Delphi。起初似乎很简单。我正在进行第二个DirectX 11教程-设置框架并使初始窗口显示出来。

现在是我真正的问题。我一直遇到访问冲突错误。因此,我找到并开始使用MadExcept来查找问题所在。它告诉我错误的行数,但我不知道如何解决这些问题。

我已经设置好了所有东西,以尽量模仿原始源代码。唯一的区别是,在变量(例如m_input、m_grahics和system)的类指针的情况下,我为这些变量制作了一个类型。所以我有TSystemClass、TInputClass、TGraphicsClass,然后我有PSystemClass等等,它们等于^TSystemClass等等。我认为这样做会使事情更简单、更整洁。另外,我假设应该说一下,但是为了构造复制构造函数,我让最初的类从TPersistent继承,这样我就可以使用它的Assign过程。

所以,回到访问冲突错误。首先,在主程序中,system是PSystemClass类型的问题。对我来说原因不明,当我尝试使用system.create时,就在那一瞬间创建了访问冲突。然后我意识到,我没有将system分配给system.create。所以我尝试了这个,它说,我想这是正确的,在编译时会出现一个错误,因为两者不兼容,因为system.create是TSystemClass类型,而system是PSystemClass类型。所以我尝试进行类型转换,那行得通。但是再次遇到可怕的访问冲突。

于是我有一个奇怪的想法,也许我应该直接从TSystemClass本身调用常规构造函数。我尝试了一下,需要再次进行类型转换。所以我做到了。它起作用了!那里不再有访问冲突错误!现在…新问题!或者在这种情况下是“问题”。在MadExcept的调用堆栈中现在列出了3件事。第一个:

m_hinstance := GetModuleHandle(nil);

它说这导致了访问冲突错误。但是为什么会这样呢?据我所知,如果GetModuleHandle设置为null/nil,则应该检索调用它的文件的句柄,对吗?从文档中可以看出,那应该是可执行文件。
但要注意:我不确定是否因为我将主程序、系统类别、输入类别和图形类别放在不同的程序/单元文件中以模拟原始源代码的性质。那么这可能是导致问题的原因吗?如果是,我该如何解决?将所有代码从单元文件中放���主程序文件中?但在我个人看来,那会非常凌乱和不直观。
接下来的问题更让我困惑。
InitializeWindows(ScreenWidth, ScreenHeight);

我这里只涉及到注册窗口类和为窗口做准备的函数,所以我不太确定问题出在哪里,因为它只涉及到两个已经定义好的参数,而且在调用之前它们已经被定义好了。所以我不太确定问题出在哪里,也不确定到底是什么原因导致了访问冲突。

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

return := system.initialize;

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

我想,如果系统无法正确执行其预定功能,则应该发生某些事情。同样,因为我之前使用TSystemClass.Create(强制转换为PSystemClass)创建了系统,那么这里会发生什么?它可能与其他两个问题有关,因为它们无法正常执行自己的操作吗?

最后要注意的是,在MadExcept的调用堆栈中还有一件事。

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

感谢您阅读到这里,并希望能够在解决此问题上得到帮助,以便我可以进一步学习。


1
这段内容过于叙述性了。你所提供的少量代码样例都嵌在冗长的段落中。发布一些代码会更简洁、易读,也比口述类型转换的使用更不容易出错。 - Cosmin Prund
2
并且,提供一些提示:当您声明一个类型为TSomething的变量(其中TSomething是一个类)时,它已经是一个指针:在移植C++代码时要考虑到这一点。当您说“^TSomething”时,就像在C ++中说“TSomething **”(双指针)。如果您硬转换TSomething为^ TSomething,您肯定会遇到麻烦。用C ++术语来说,你只是将“TSomething *”强制转换为“TSomething **”。而访问冲突“pop”的位置并不总是表示错误的原因。尝试使用FastMM4与完整调试来诊断AV和内存损坏。 - Cosmin Prund
1
我们不会给您发送电子邮件。如果您展示一些代码,我们可能能够帮助您。 - David Heffernan
1
我们不会给您发送电子邮件,但是垃圾邮件发送者可能会。 - Cosmin Prund
我回家后可以查看您的代码,但我猜测Cosmin Prund是正确的,您可能会搞混类变量和指针。如果您在调用无效或nil的类引用上调用Initialize,则可以解释访问冲突m_hinstance := GetModuleHandle(nil); 。AV并非由GetModuleHandle调用引起,而是将GetModuleHandle的结果赋值给m_hinstance引起的。 - The_Fox
显示剩余5条评论
2个回答

5
您实例化类的方法不正确。以下是TSystemClass.Initialize的示例:
m_Input := PInputClass(m_Input.create);

这是你声明为PInputClass的变量。

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

m_Input := nil;

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

该构造函数返回你构造的类型的值,即 TInputClass。它不返回 PInputClass,因此你的类型转换是错误的。正如 Cosmin 的评论所解释的那样,Delphi 对象变量已经是指针了。基于 Delphi 类声明指针类型是非常罕见的。正确的代码应该是:

m_Input := TInputClass.Create;

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

我是否漏掉了一些显而易见的东西?你所提到的代码在哪里? - David Heffernan
我明白了,这很有见地!非常感谢!所以,现在我相信我已经正确地实例化了所有的类。虽然现在我仍然在MadExcept的调用堆栈中收到关于TSystemClass构造函数的一些信息。无论顺序如何,在Inherited之后的第一段代码总是罪魁祸首。如果我去掉对m_input和m_graphics的nil赋值,那么它似乎会抱怨构造函数的end;。 - Asurai Valentine
虽然我现在有一个更新的链接 - 变化不大,但至少是我之前提到的那些。http://www.mediafire.com/?z9g51zlrb89d998 这里是调用堆栈的图像。可能比我解释起来容易得多。(而且我不太擅长用语言)http://i252.photobucket.com/albums/hh33/Asurai_Asureflame/MadExcept_CallStack.png - Asurai Valentine
就像我说的那样,在 main.dpr 中你实例化系统类的方式是错误的:system := system.create。你应该像在其他所有 Delphi 程序中创建对象一样创建它:TSystemClass.Create。我建议不要使用 "system" 作为变量名,因为它会隐藏 System 单元。 - Rob Kennedy
2
我愚蠢地忽略了那个。抱歉。但是之后它现在可以工作了!虽然当按下escape键时会抛出异常。不过如果我无法解决这个问题,那么我可能会说现在是提出另一个问题的时候了。非常感谢你,Rob!你真的是救星。而且你们这里的工作速度真的很快 o.o 在其他地方,要达到这个程度可能需要很长时间~ - Asurai Valentine
显示剩余2条评论

2

首先,您应该尝试摆脱TPersistent继承。如果您想将对象传递给库,其接口应与在C++中使用的原始接口完全相同。通过从TPersistent继承,您会将许多负载带入您的类中,这可能是不必要的,甚至可能是问题的原因。

此外,如果您发布异常的确切输出,甚至是CallStack,那可能有助于追踪错误。


1
非常抱歉,大家。但是我觉得我需要对一切进行解释,并且认为仅仅发布300多行代码之类的东西对任何人都没有帮助。虽然我再次为非常小的代码片段道歉。这是我的整个项目的媒体火链接。http://www.mediafire.com/?82w27c08d4fk6tg 我已经删除了指针类和复制构造函数。我不知道它们是否会被实现,但如果它们被实现,我会在那时处理。感谢大家迄今为止的建议! - Asurai Valentine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接