4
votes

I wasn't entirely sure how to name this, so apologies in advance.

You see, I'm trying to teach myself Win32/DirectX programming, utilizing Delphi (my language of choice) using this site - http://rastertek.com/tutindex.html

Of course, the site being all in C++, I have to port it to Delphi. It seemed simple enough, at first. I'm on the second tutorial for DirectX 11 - setting up the framework and getting the initial window to show up.

Now for my actual problem. I was getting Access Violation errors. So I found and started to use MadExcept to try and find out what was going on. So it tells me the lines, but I'm clueless as to how to solve the issues at hand.

I have everything set up to mimic as well as I can the original source code. The only real difference being that in the instances where a pointer to a class for a variable, such as the case with m_input, m_grahics, and system, I made a type for those. So I have the TSystemClass, TInputClass, TGraphicsClass, and then I have PSystemClass, etc. that = ^TSystemClass, etc. I figured that this would make things a bit simpler and more neater. On a side note, I assume it should be said, but I for the construction of the copy constructors made the initial classes inherit from TPersistent so I could use it's Assign procedure.

So, back to the Access Violation errors. So first, the problem was in the main program with system being of type PSystemClass. So for a reason unknown to me, when I tried to use system.create, it was at that very instant, creating the access violation. I then realized however that I wasn't assigning system the system.create. So I tried this, and it said that, and rightfully so I suppose, at compile time an error that the two were incompatible since system.create is of type TSystemClass, and system is of PSystemClass. So I tried typecasting it, and that worked. but once again, still getting the dreaded access violations.

So then I had an odd idea, maybe I should call the regular constructor right from the TSystemClass itself. And I tried, needed to typecast again. So I did. And it worked! No longer an access violation error there! Now... New problem! Or rather in this case "problems". There's 3 things now listed in the call stack in MadExcept. The first one:

m_hinstance := GetModuleHandle(nil);

It's saying that this is causing an access violation error. Though why is this, exactly? From what I understand and have read, if GetModuleHandle is set to null/nil, it should retrieve the handle for the file that called it, right? And from what the documentation says, that should be executable.

However note: I'm not sure if the fact that I have the main program, the systemclass stuff, the inputclass stuff, and the graphicsclass stuff, all in different program/unit files to mimic the nature of the original source code. So is this possibly what's causing it? And if so how would I fix it? By putting all of the code from the unit files into the main program file? Though that, in my own personal opinion, would be quite messy and unintuitive.

The next one baffles me even more.

InitializeWindows(ScreenWidth, ScreenHeight);

I'm not dealing with anything other then a function to register the window class and set things up for the window and all here. So I'm not quite sure what the problem here is since it only deals with 2 parameters and they're defined and all already before it's called. So I'm not quite sure what the problem here is at all and what exactly is causing the access violation.

and then finally the final one is in the main program:

return := system.initialize;

Return is what I used in all instances of the result variable of the original source code, as result is of course a built in variable of all functions.

I suppose if system is never able to properly do what it's meant to do then something could/should happen here. Likewise, because I used TSystemClass.Create (typecasted to PSystemClass) earlier to create system would that do anything here? And is it possibly linked to the other two because they're not able to do their own thing properly?

And on a final note; there is one last thing actually on the call stack in MadExcept.

It says Kernel32.dll in the module section, but aside from the main thread, it lists nothing else. (If this information is needed I'll gladly put it up).

Thanks in advance to anyone who's read this far and I hope to find some help on this problem so I may further my studies.

2
This too narrative. The few code samples you've got are embedded in long paragraphs of text. Posting some code is shorter, easier to read, and less error-prone then saying narrating your use of typecasting.Cosmin Prund
And to give some tips: When you declare a variable of type TSomething (where TSomething is a class), it's already an pointer: Take that into consideration when porting C++ code. When you say ^TSomething it's like saying TSomething ** in C++ (double pointer). If you hard-cast TSomething to ^TSomething you're of course going to get in trouble. In C++ terms, you've just casted TSomething * to TSomething **. And the location where an Access Violation "pops" is not always indicative for the cause of the error. Try using FASTMM4 with Full Debug to diagnose AV's and memory corruption.Cosmin Prund
we're not going to email you. We night be able to help you if you showed some code.David Heffernan
we're not going to email you, but the spammers will.Cosmin Prund
@Asurai Valentine, I have removed the email addresses. We like to keep all information on stackoverflow for future references. Besides we don't like to facilitate spammers.Toon Krijthe

2 Answers

4
votes

You're instantiating your classes all wrong. Here's an example from TSystemClass.Initialize:

m_Input := PInputClass(m_Input.create);

That's a variable you declared as a PInputClass.

Earlier, in TSystemClass.Create, you initialized that variable:

m_Input := nil;

So, since you have a null reference, it should be clear that you can't call any methods on it. In particular, you cannot call Create on it. Instead, call Create on the class you want to instantiate: TInputClass.Create.

That constructor returns a value of the type you constructed, a TInputClass. It doesn't return a PInputClass, so your type-cast is wrong. As Cosmin's comment explains, Delphi object variables are already pointers. It's exceedingly rare to have to declare a pointer type based on Delphi classes. The correct code is this:

m_Input := TInputClass.Create;

After that line, you check whether m_Input is null. You never have to do that in Delphi; a constructor either returns a valid object, or it doesn't return at all. If there's a problem constructing an object, the constructor throws an exception and the assignment statement never executes. (The original C++ code does it wrong, too. The new operator hasn't returned a null pointer on failure for over a decade, long before anyone was in a position to start writing a DirectX 11 tutorial.)

1
votes

You should first of all try to get rid of the TPersistent inheritance. If you want to pass an object to a library its interface should be exactly the same as the original that is used in C++. By inheriting from TPersistent you take a whole lot of load into your class that might be not needed or might even be the reason of your problems.

Additionally it would help if you posted the exact output of the exceptions. Or even the CallStack. That might help tracing down the error.