Re: Bug in my C++ program seems really strange. (Update on debugging progress)
On Sep 1, 3:38 pm, "Alf P. Steinbach" <al...@start.no> wrote:
* mike3:
On Sep 1, 12:57 am, "Alf P. Steinbach" <al...@start.no> wrote:
* Gianni Mariani:
mike3 wrote:
On Aug 31, 10:32 pm, "Alf P. Steinbach" <al...@start.no> wrote:
...
http://www.mediafire.com/?cfmzd1y3yij
How does one build all that ?
Changes to make it /compile/:
fracalg\computefrac.cpp(371):#if 0 //APS
fracalg\computefrac.cpp(378):#endif //APS
fracalg\computefrac.cpp(393):#if 0 //APS
fracalg\computefrac.cpp(396):#else //APS
Excuse me, why all this? Those were commented
out for debugging purposes to help minimalize
the code.
I don't remember but I think you can figure it out. :-)
fracalg\computefrac.cpp(397): err = FG3DError(FG3D_INVALID_FRACTAL_TYPE,
FractalType); //APS
fracalg\computefrac.cpp(398):#endif //APS
This too.
This I think I remember. You called some fractal computation functions
that you didn't supply.
Darnit, I forgot to remove the references in
stripping. I'm updating my main program, by
the way, to take into account all these
things you've mentioned.
render\render.cpp(51): //APS MessageBox(NULL, TEXT("Zorg."),
TEXT(""), MB_OK);
render\render.cpp(69): //APS MessageBox(NULL, TEXT("Borg."),
TEXT(""), MB_OK);
Why couldn't it compile with those in?
Would compile but would not work, just silent termination. Don't set up
message loops in rendering. Btw., that has nothing to do with C++.
OK.
win32\CMainWnd.cpp(52): wcx.hCursor = LoadCursor(0,
IDC_ARROW); //APS LoadCursor((HANDLE)NULL, IDC_ARROW); /* cursor */
win32\fg3dImageWindow.cpp(34): wcx.hCursor =
LoadCursor(0,IDC_ARROW); //APS //LoadCursor((HANDLE)NULL, IDC_ARROW); /*
cursor */
win32\fg3dNewImageWzrd.cpp(18)://APS HWND gTmp;
win32\fg3dNewImageWzrd.cpp(32)://APS gTmp = hwndTmp;
main.h(108)://APS extern HWND gTmp;
fracgen3d.cpp(79):// APS
Plus, the WinMain function must be changed to something like
int WINAPI WinMain(HINSTANCE TheInstance, HINSTANCE LastInstance,
LPSTR lpszCmdLine, int iCmdShow)
{
__try
{
return cppWinMain( TheInstance, LastInstance, lpszCmdLine,
iCmdShow );
}
__except(TRUE)
{
TCHAR szBuf[256];
StringCchPrintf(szBuf, 256, TEXT("EXCEPTION %08lX"),
GetExceptionCode());
OutputDebugString(szBuf);
return 0;
}
}
where cppWinMain contains the original code for that __try.
It's funny (is that the right word?) when the code contains C style
casts that makes it not compile, when all that's needed is to remove
those casts...
I must be using a really crappy C++ compiler then as
it allows that stuff.
Yes. In addition it seem you're not using your compiler in the best
possible way. After upgrading to a better compiler, turn on all
standard-conformance and all warnings, make the thing compile cleanly.
What would be a better compiler, by the way? I've only
got this one since I didn't have to pay money for it
and I do not have a lot of money.
So then it casts it automatically, you don't need all
that C-style stuff, then? Darn I'm too paranoid.
No, it's good to be paranoid in coding. But introducing casts is the
opposite of being paranoid: you're turning off all checks!
To be sufficiently paranoid you need to do the /opposite/: no casts.
Or at least as few as possible, and none in high-level code.
OK.
Then I'd be curious to know. Does this require a cast,
to get the value of the pointer for our error information?:
FG3DError SomeRoutine(BigFloat *a)
{
FG3DError err;
<blah blah blah>
if(<some operation on "a" failed>)
return(FG3DError(<Error code>, a)); <--- here
else
return(FG3DError(FG3D_SUCCESS));
}
And this?
long MultiplyShorts(short b, short c)
{
long a;
a = b*c;
return(a);
}
Will this give the full "long" result or
do I need to typecast b and c to "short"?
And will it do that on all compilers (in case
I change my choice of compiler in the future),
ie. is that "standard" behavior? Especially
that last part right there -- is it _standard_
for a = b*c to be the full long product of b
and c, or not? I need that long product!
or this?:
double DivideInts(int a, int b)
{
double t;
t = a/b;
return(t);
}
Does that give a full floating-point double-
precision quotient of a and b or an integer one?
By the _C++ standard_, remember. See, in all
three of these situations I've used a cast, and
it is these situations that account for the vast
majority of my cast use.
Having done all the above the program crashes on using an invalid
pointer txtrptr in [render.cpp] at line 62, which is due to using an
uninitialized member "d3dlr" (presumably there should have been an
earlier call to FractalImage::LockRectangle, but no such).
That is uninitialized? It calls LockRectangle() right
in there @ line 46.
I'm just reporting what it did. There was no actual call to that
function at run-time, before the crash. As to why that should happen,
well. :-)
Uh oh...
Why wouldn't it call? That does not make any sense! It
calls on my machine.
Yes, I must be very bored to do such a thing! :-)
Cheers, & hth. (although I didn't look at the silly bignum class,
whatever its fault is, it may just be corrupted memory in general),
I've had a bear of a time trying to track it down.
General advice: in lots of places in the code there are checks whether
something is initialized or not.
I'm paranoid.
If you instead make sure that constructors either initialize completely
and successfully, or else throw exceptions, you will only have properly
initialized objects around, and so you won't have to do that complicated
and leg-breaking dance.
The constructors do throw exceptions if they cannot initialize
something
completely and successfully. So it would be OK to remove all
initialization
checks except the exception throwing, then?
Where it seems that you absolutely need some halfway initialized state,
like, calling a common Init function, consider replacing that Init
function with a proper constructor in a private base class (of course
this most often indicates a design issue, but better with a technical
fix than having that halfway initialized state causing general mess).
The reason I chose the "Init" function in the bignum "BigFloat"
thing was beacuse I would have to repeat the same memory-allocation
code in each constructor so I wanted to save some space. I heard
repetition of code wasn't a good idea, so I just encapuslated
that code which would be identical between the constructors
in a nice, easy-to-service routine called "Init". "Init"
is never called anywhere else except in constructors for
BigFloat (it's a "private" member function as well.). At no
point do I need a "half-initialized" something. Whenever I
need it initialized in a certain way, I just make another
constructor for that (For example there's a constructor that
will initialize a BigFloat to a given "double" float.).
That's all I have that for, to make maintenance easier and
to avoid repetition.
Cheers, & hth.,
- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?