• Advertisement

Archived

This topic is now archived and is closed to further replies.

What. The. HELL?

This topic is 5836 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been working on some fairly simple code, and totally rewriting some stuff I did a long time ago. I have encountered an error whose only logical explanation would appear to be demonic possession. If anyone can tell me why this is occuring, or give me the name of a good exorcist, I'd be grateful. First, a little information about what I'm doing: I'm trying to write a small sprite library that uses DirectDraw. To help me with all my coding needs, I've written a really simple function that takes a string as an argument and writes it to a file called ErrorRecord.txt. This way, I can easilly tell when and where problems are occuring. This function is called Rec(). I've written a program that uses DirectDraw to perform the adventurous task of changing the resolution. When a key is pressed, the program exits. Yes, I know, it's glorious. Thank you for that standing ovation. Now I'm attempting to add some code for manipulating sprites, one incredibly small step at a time. I have written a class, called Sprite, with almost nothing in it:
  
class Sprite{
	public:
		Sprite();
		~Sprite();
		bool LoadBitmap(char * filename, LPDIRECTDRAW lpdd);
	private:
		LPDIRECTDRAWSURFACE imageSurface;
};    
The constructors and destructors look like this:
  
Sprite::Sprite()
{
	Rec("Default constructor for Sprite class invoked.");
	
	imageSurface = NULL;
}

Sprite::~Sprite()
{
	Rec("Destructor for Sprite class invoked.");
	
	imageSurface->Release();
}    
Not exactly a lot of room for error so far. LoadBitmap() has been written, but isn't invoked anywhere, so I'm not listing it here. Now, in WinMain, I have something that looks like this:
  
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE ignoreMe, LPSTR arguments, int showStyle)
{
	MSG recentMsg;
	
	ClearRec();
	Rec("Program Launched. Beginning Initialization...");
	
		// Attempt to initialize.

		if(!InitializeAll(hinst, showStyle))
		{
			Rec("Error during Initialization.");
			return 1;
		}

...(other stuff)...
    
ClearRec() just empties the previous Error Record. InitializeAll looks like this:
  
bool InitializeAll(HINSTANCE hinst, int showStyle)
{
	HWND hWnd;
	WNDCLASS wc;
	
	srand((unsigned)time(NULL));
	primaryWindowHandle = NULL;
	
	// *** Window Initialization ***

	InitDefaultWindowClass(&wc, hinst);
	
	Rec("Registering class.");
		if(!RegisterClass(&wc))
		{
			Rec("Error registering class.");
			return false;
		}

       ... (more initialization stuff) ...

        Rec("Allocating sprite.");
	exampleSprite = new Sprite;
	Rec("Sprite allocated.");
	
	Rec("Initialization Successfully Completed.");
	return true;
}
   
Now, here's the problem. If I take the EXACT code I have right there, and comment out the line "exampleSprite = new Sprite;", the code works perfectly . No problems whatsoever. However, with that line in, the program quits out earlier, and my Error Record.txt looks like this:
  
Sun Feb 24 02:26:11 2002 Program Launched. Beginning Initialization...
Sun Feb 24 02:26:11 2002 Registering class.
Sun Feb 24 02:26:11 2002 Error registering class.
Sun Feb 24 02:26:11 2002 Error during Initialization.
    
HOW CAN THIS BE? The line exampleSprite = new Sprite; is found AFTER the window class registration! Through what occult powers has it come to pass that the existance of this line causes the code to fail BEFORE THE LINE IS EVEN ENCOUNTERED? Has this error mysteriously traversed the temporal continuum for the sole purpose of causing my program to fail? If anyone knows how this is happening, please, let me know. Alternately, if you agree that this is really weird, let me know that too The compiler I'm using is an older Metrowerks one. (Edited to switch the code tags to source tags) Edited by - Zorodius on February 24, 2002 8:29:13 AM

Share this post


Link to post
Share on other sites
Advertisement
Further testing would seem to reveal that the only way to make this functional is to comment out the constructor for the Sprite class. Even if there is no code whatsoever in the sprite class constructor, it causes my program to fail at the window class registration phase. However, if I comment out the constructor entirely, it works just fine (although the destructor must be modified such that it is not releasing an unallocated object, but the program itself proceeds precisely as would be expected.)

I changed "imageSurface->Release();" to "if(imageSurface != NULL) imageSurface->Release();", because this was obviously wrong, but it didn't affect anything.

I also thought the problem might be related to my choice of names - maybe there was another Sprite type already defined, and it was creating problems somehow. I tried adding on some random letters, changing "Sprite" to "NZXSprite", and that also had no effect.

Why would the existance of a constructor in a totally seperate class cause this program to fail at the WNDCLASS registration? Particularly when that constructor has not been invoked and contains no code ? Maybe it's merely symptomatic of another problem, but it's extremely clear that, for whatever reason, having the constructor in existance causes the call to RegisterClass() to fail.

Demonic possession is sounding more and more likely.

Edited by - Zorodius on February 24, 2002 10:06:39 AM

Share this post


Link to post
Share on other sites
well, i haven''t had a whole lot of practice with directX, but one thing caught my eye. in your InitializeAll function, you set primaryWindowHandle = NULL; is primary a global? i assumed so due to no local declaration. that would probably cause other directX functions to fail if it didn''t have a handle. just my 2 cents.

cyn

Share this post


Link to post
Share on other sites
In the error log you give, there isn''t a logging message from the constructor, nor your "Allocating sprite." message. Did you edit those out, or are they really not showing up?

I think there is something else going on here. Most likely things are getting initialized in the wrong order.

Take care,
Bill

Share this post


Link to post
Share on other sites
You''re right, it is a global, and it would create problems if it wasn''t set to something. It is correctly set, though, in the section of code I replaced with "... (more initialization stuff) ..." (for brevity''s sake).

Just in case, here is the InitializeAll function in it''s complete form:

  
bool InitializeAll(HINSTANCE hinst, int showStyle)
{
HWND hWnd;
WNDCLASS wc;

srand((unsigned)time(NULL));
primaryWindowHandle = NULL;

// *** Window Initialization ***

InitDefaultWindowClass(&wc, hinst);

Rec("Registering class.");
if(!RegisterClass(&wc))
{
Rec("Error registering class.");
return false;
}

Rec("Creating window.");
hWnd = CreateWindow(VERSION, VERSION, WS_POPUP, 0, 0, SCREENWIDTH, SCREENHEIGHT, NULL, NULL, hinst, NULL);
primaryWindowHandle = hWnd;

ShowWindow(hWnd, showStyle);
UpdateWindow(hWnd);

// *** DirectDraw Initialization ***

DirectDrawCreate(NULL, &lpDD, NULL);
lpDD->SetCooperativeLevel(hWnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT);
lpDD->SetDisplayMode(SCREENWIDTH, SCREENHEIGHT, SCREENDEPTH);

DDsd.dwSize = sizeof(DDsd);
DDsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
DDsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
DDsd.dwBackBufferCount = 1;

Rec("Creating primary surface.");
if(lpDD->CreateSurface(&DDsd, &primarySurface, NULL) != DD_OK)
return false;

DDSCaps.dwCaps = DDSCAPS_BACKBUFFER;

Rec("Getting attached surface.");
primarySurface->GetAttachedSurface(&DDSCaps, &backSurface);

Rec("Allocating sprite.");
exampleSprite = new Sprite;
Rec("Sprite allocated.");

Rec("Initialization Successfully Completed.");
return true;
}

Share this post


Link to post
Share on other sites
quote:
In the error log you give, there isn't a logging message from the constructor, nor your "Allocating sprite." message. Did you edit those out, or are they really not showing up?


You are completely right, and that is precisely why this problem is so confusing to me. They really aren't showing up. Somehow, the existance of the constructor creates problems even though the constructor is never invoked .

Edited by - Zorodius on February 24, 2002 11:22:19 AM

Share this post


Link to post
Share on other sites
quote:
Don''t you have to fill in some fields in the WindowClass structure?


Sure do, which is why the InitDefaultWindowClass(&wc, hinst); call is made. That was also left out for brevity''s sake.

Just in case, here it is:
  
void InitDefaultWindowClass(WNDCLASS * wc, HINSTANCE hinst)
{
wc->lpszClassName = VERSION;
wc->hInstance = hinst;
wc->lpfnWndProc = ProcessMessage;
wc->hCursor = LoadCursor(NULL, IDC_ARROW);
wc->hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc->hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wc->style = 0;
wc->cbClsExtra = 0;
wc->cbWndExtra = 0;
}

Share this post


Link to post
Share on other sites
You are setting primaryWindowHandle = hWnd and then continueing to use hWnd, which would make primaryWindowHandle out of date.

Assuming you are using primaryWindowHandle for something, you need to use it for all the initialization functions, not hWnd (including ShowWindow and UpdateWindow).

Edit.. though your code does not seem to even get that far. Hmm.

Edited by - BenHanson on February 24, 2002 11:57:32 AM

Share this post


Link to post
Share on other sites
Hate to use up my 100th post on this (look at the date I registered and you may understand - I wonder if anyone else who has been around this long as fewer posts than I)...

Anyway, if RegisterClass fails, make a call to GetLastError() and see what it''s returning. You can use ErrLook to find out what the value is. This should tell you why RegisterClass is failing, or at least point you in the right direction.



Mark Fassett
Laughing Dragon Entertainment
http://www.laughing-dragon.com

Share this post


Link to post
Share on other sites
try using "rebuild all" - VC might be trying to link 2 different versions of the code together. that sometimes happens to me when it errs for no reason.

Share this post


Link to post
Share on other sites
You know, also weird things happen when you start writing a
windows console application and write it with all the windows
stuff. Try building the project again from scratch, with a
mew win32 application in the project window. Heh I was writing
a sample program, and spent 30 mins debugging it trying to figure
out why it didnt work, and why it was returning strange values
from WinMain when I clearly wrote
return 0;

I mean the program was like 5 lines long. All it did was make a
messagebox, and as far as I could tell, I wasn''t insane.

If you also get return codes from WinMain like
0x-2489872cfe23
Then probably that will work.
Who knows, give it a shot. *shrug*

-=Lohrno

Share this post


Link to post
Share on other sites
you''ve debugged the code, right? Stepping through it would work, as it isn''t working at all.

/j

Share this post


Link to post
Share on other sites
quote:
Original post by LaughingD
Hate to use up my 100th post on this (look at the date I registered and you may understand - I wonder if anyone else who has been around this long as fewer posts than I)...


I have been here since the first day of the gamedev forums, originally under the name ''Piccolo'', combined both accounts have 86 posts (well, 87 now)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
try turning optimisations off in the compiler - it MAY be reordering your instructions to get a speed increase...

Share this post


Link to post
Share on other sites
Sorry, I have no idea whats causing this error, but i noticed 2 things about ur code. You are using the class LPDIRECTDRAWSURFACE. I''ve only worked with ddraw in DX7, and as far as I know, LPDIRECTDRAWSURFACE is they class from DX5, and the most recent one is LPDIRECTDRAWSURFACE7.
Also, wouldn''t it be easier to use the fstream classes for your log file? Thats what I do. Since you''ve already made the function I guess it doesn''t make a difference.

Proceeding on a brutal rampage is the obvious choice.

Share this post


Link to post
Share on other sites
Well, if your doing a simple class just use the CDisplay class that comes with the DirectX SDK. Its common ground thats already been debugged. Also why in the world would anyone use Metrowerks... i haven''t EVER seen a worse compiler. Theres a free one thats better. Its like www.bloodshed.net maybe .com can''t remember exactly. Also you probably should pass the lpdirectdraw around, just make it global.

PaladinGLT

Share this post


Link to post
Share on other sites
AAAAAAAAAHHHHHHHHHHHHHHH!!!!111!
faskd;fjsak
;fsakf
sdalksadf
klsadf

Okay, stress relief complete. Permit me to update the information regarding this situation.

First of all, thank you all for your many fine suggestions regarding this problem. As it turns out, they worked - in fact, it is their simple existance and abundance that have allowed me to successfully isolate this problem.

And what problem is that?

IT''S THE COMPILER.

That is a sentence which I previously believed was only spoken in error. Or in Visual Basic. But mostly in error.

But it really is the compiler, this time!

I have modified the beginning of my InitializeAll function to allow me to record the error codes generated by this "mysterious error" that I have spent the past couple nights bitterly attempting to find.

The code looks like this:

  
bool InitializeAll(HINSTANCE hinst, int showStyle)
{
HWND hWnd;
WNDCLASS wc;
int errorNumber;
char errorString[51];

srand((unsigned)time(NULL));
primaryWindowHandle = NULL;

// *** Window Initialization ***

InitDefaultWindowClass(&wc, hinst);

Rec("Registering class.");
if(!RegisterClass(&wc))
{
//errorNumber = GetLastError();

Rec("Error registering class.");
//sprintf(errorString, "Error #%d", errorNumber);

//Rec(errorString);


return false;
}


This code operates in precisely the erroneous fashion described earlier (screws up at the class registration phase). You will notice that the lines of code pertaining to the actual recording of the error value are commented out.

If I make no other changes whatsoever, and remove the commenting from these lines, the program works . Really, I''m not kidding. Even though it never actually executes those lines to the best of my knowledge (and to the best of the knowledge of my handy-dandy log file), the program works flawlessly, simply because I have introduced code that never executes.

But that''s not all! I was considering the suggestion AP made about turning off the optimizations. The kicker was, see, the optimizations WERE off. So, logically enough, I tried turning them on . Viola, the code works. Even with the debugging lines mentioned above commented out.

So that''s two ways of causing the program to work without making any modification to the code itself. The third I found was to simply copy out the section of code pertaining to the window class registration and paste it into the WinMain entry-point routine. That difference-that-makes-no-difference (since, after all, that''s precisely the sequence of events that would normally have been occuring anyway) also caused the program to work.

In the face of such overwhelming evidence, I am forced to conclude that it is the compiler''s fault, my code is flawless, and I deserve a million dollars. And a homemade cherry pie.

Again, I would like to thank all of you who replied, because your advice was extraordinarilly helpful.

And, uh, does anyone know of a good compiler? Metrowerks is off my list (not that I chose it in the first place, but that''s besides the point), and I''m wary of VC++ because VB has clearly demonstrated itself to be a digital turd in the past.

If all compilers suffer from this kind of failing (I had a similar problem with VB under different circumstances, although it was much easier to isolate), then debugging code for a living must just be a living hell. Perhaps I should consider a less stressful career choice, like... oh, I don''t know, hostage negotiator, military codebreaker, medical test subject, or bodyguard for a high-profile fundamentalist islamic terrorist warlord.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You know, if you aren''t flushing your output stream after every write, then you may not be seeing all of the error logging that your program was trying to output.

Share this post


Link to post
Share on other sites
I''m using the stdio functions for file manipulation. (fopen, fwrite, fclose)

Every time Rec() is called, it opens, writes to, and closes the error record, so that I will still have a meaningful record even in the event of a crash.

Share this post


Link to post
Share on other sites
Have you declared exampleSprite as a type (of class) Sprite ?

Metrowerks is very poor (my opinion), Try DevC it seems to be a popular choice round here.

,Jay

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
What it sounds like to me is that the change in code causes the memory values to change, which ends up setting an uninitlized varible to be right sometimes, and not right othertimes.

So, where''s the uninitialized varible..? The only one I see is in InitDefaultWindowClass, you never initialize wc->lpszMenuName, nor do I see anything clearing the entire structure or otherwise indicating it''s set to NULL or some proper value...so that varible not being initialized is my guess.

Share this post


Link to post
Share on other sites
quote:
All of you are wrong! The code is an ancient satanic ritual...

Close! I''m attempting to resurrect the ancient Babylonian God of Chaos to wreak untold havoc and suffering upon those unfortunate enough to be imprisoned in this mortal plane.

However, that''s not it.

quote:
The only one I see is in InitDefaultWindowClass, you never initialize wc->lpszMenuName

Crow tastes like chicken

You''re right, that was the problem. Today, I have learned a valuable lesson in respect for the importance of all the fields of the mighty WNDCLASS.

I really had no idea. I just assumed that, because the problem was so repeatable and could be changed by things totally unrelated to the code itself, it wasn''t caused by anything like that. But it was, and it makes sense now.

Share this post


Link to post
Share on other sites
You might want to give MSVC another look. I''m using visual studio.NET and have used visual studio 6, and I have to say that the development environments are unmatched in quality. The compiler proper is pretty decent, although there are some conformance issues. You can always plug in the intel compiler though.

Plus, MSVC is the industry standard for windows programming, so you get good experience for a later job too =)

Share this post


Link to post
Share on other sites

  • Advertisement