Bug in my C++ program seems really strange. (Update on debugging progress)

M

mike3

I think it just does c++ but it has an IDE. You can also get Borland's
Turbo
Explorer that's based on BDS2006. It has an IDE and a newer compiler
than 5.5. Or just get both and see what you like. Both are free.

What's it called, anyway?
 
A

Alf P. Steinbach

* mike3:
I use the Borland C++ Builder 5.5 Command line tools.


Gratis, really?
Yep.


Is there a "stripped" version that has only the
C++ compilers, like with the Borland thing?

Not as far as I know, but unless it's very different from 7.1 you can
use the command line tools separately from the IDE.

[snip]
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));
}
Do something like

void someRoutine( BigFloat const& a )
{
// some operation on "a"
}

If "some operation" fails it will throw an exception.

What if the operation though is something that returns
an error value instead?

The you convert to exception.

Fair warning: code below is my preferred way but many programmers find
it unnatural. If you find it unnatural, just replace "||" with "if".

bool throwX( char const s[] ) { throw std::runtime_error( s ); }

void someRoutine( BigFloat const& a )
{
someOp( a ) == NO_ERROR || throwX( "someRoutine: someOp failed" );
}

Oh and when I throw the exception
I also need to convert a pointer to give additional
information to whatever handler catches the exception,
(there's handlers in any area where exceptions may
get thrown out of) for example to show that an
operation on "a" failed.

That seems to a requirement that stems from a particular current
solution. When replacing the current solution the requirement then
disappears.


Should there be _no_ functions that return error
values, and instead _always_ throw exceptions when
they fail (as that way you don't have to worry about
neglecting an error check around one, you can just
keep a few exception handlers at various levels,
etc.?)?

Personal preference. There is a run-time cost associated with throwing
exceptions, and that needs to be weighted against clarity and ease of
programming: running time versus programmer's time and correctness. But
in general, as long as the program is fast enough, exceptions are in my
experience preferable even when the situation is not "exceptional".
However, it's /very important/ to think about simplicity of /usage/.
For if using the function will then require a try/catch in the immediate
caller for the most common usage, then exceptions are strongly
contra-indicated -- most try/catch-es indicate a possible improvement.


[snip]
No, in the code you showed the arguments would be promoted to int, the
computation done as int, and only then the result converted to long.

So then you have to typecast, right?
Nope.


[snip]

So then would a typecast be a good idea?

Or is does this do it, and is it "proper"?:

---
double DivideInts(int a, int b)
{
double adbl = a;
double bdbl = b;

return(adbl/bdbl);
}

This is good, but perhaps even better:

double doubleDiv( int a, int b ) { return 1.0*a/b; }

For some reason I like one-liners... :)

Any half-decent compiler should optimize away the "1.0*". What it does
is to force a promotion to double of a and b. Before anything else.


[snip]
It works now! The bug has been fixed!
Good.


The Init functions are *pnly* and I say again, *ONLY*
called in CONSTRUCTORS, period. And *always* called from
them. They're just there to save a bit of cutting-and-
pasting. At no point are they called anywhere else.

By expressing them as constructors (of e.g. a private base class) you
express that in code, /ensuring/ that they're not called from anywhere
else, and so making it completely safe to remove initialization checks.


[snip]
Could you tell me where my design is wanting, by the way?
I'd like to know so I can improve it.

Please note first that /every/ design is wanting.

There is no such thing as a prefetc design.

So the question is where to draw the line of possible improvement versus
work.

Since the present design is causing trouble, that line is not yet reached.

I'd start by a physical repackaging, not design. Currently, 'main.h'
(or something) is included everywhere, and a module's implementation
does not include the module's own header file. That should be exactly
opposite, for a great number of reasons, one of which is that currently
any change of 'main.h' forces a recompilation of (nearly) everything.

The main design problem I saw, with just a cursory look at the code, was
a mix of very high level (abstract operations) and low level (pointers,
casting), an abstraction gap, indicating one or more missing
intermediate levels.

Try to encapsulate low-level operations in some not-very-high-level
classes. For example, such encapsulation classes, or functions, do all
pointer stuff, translate from error codes to exceptions, etc. Just
getting that bug-inducing low level stuff /out of the way/, packaged.

Else-thread I have already mentioned another aspect of that high level
low level clash, that it would be a good idea to use std::vector instead
of raw arrays and pointers.

I think the above is the most important. But since no design is
prefetc, having done this other possibilities (including replacing
Init-functions with constructors, if not yet done) will suggest
themselves. The important thing then is to be very aware of whether the
improvements fix current bugs, prevent future ones, help future
maintainance, help reuse, or what. If the gain is not clear, but is
just "feels more elegant", then possibly the line has been reached.


[snip]
Signature snipped.

Ah, thanks.

Cheers, & hth.,

- Alf
 
B

BobR

WHAT THE.... I don't see my post, but, it must be somewhere... you are
replying to it. ????
He was using GNU compilers?

No. GNU is an operating system (OS), you might know it (incorrectly) as
Linux (which is a popular 'kernel'). The proper way to refer to it is
"GNU/Linux", (assuming the OS is GNU and the kernel is Linux).
I thought there
were versions of the GNU compilers for Windows.

That would be the GCC ports to windows, "MinGW" or "Cygwin".

If his compiler, GNU or otherwise, was unable
to support Windows he couldn't have run the
program as the whole "main" thing, "wnd" stuff
was all Windows. I'm guessing his compiler did
support Windows since he was able to run it
without modifications _that_ extensive.

What I was getting at is that with the windows stuff it couldn't compile/run
on an GNU/Linux system (unless it was cross-compiled, and run in an emulator
(like Wine)). The windows part is not considered on-topic in this NG.
What compiler do you use, by the way?

GCC (MinGW on the win partition)
I've got a
version of the GNU compilers on my system too,
and I could feed the non-Windows stuff through
it.

If it's MinGW or Cygwin, it most likely has the windows headers, and you
will be able to compile window$ programs.
If you're using GNU compilers (as I've
assumed from your "GNU don't play that!" comment),
could you explain how you do this (the "set it up
for standard compilance" part. I already know
how to raise the warning level.).

For GCC, use compiler flags -ansi -pedantic, and/or one of the 'std=' flags.
(no compiler is 100% standard compliant, though I've heard Comeau comes
close.).
Well I've been converting my main program to use
these.

But only where the compiler complains and you are *sure* it is ok to
convert, right? <G>
The first thing to do with C-style casts is remove them. Then if the
compiler barks at you, feed it an proper C++ cast.
If you're not sure, start with a static_cast, it's the safest. Be careful
with the rest.

[ some is my opinion. Corrections welcome. ]
 
M

mike3

* mike3:








Yep.

Cool. What is it called, anyway?
Not as far as I know, but unless it's very different from 7.1 you can
use the command line tools separately from the IDE.

Where can I get it, anyway?
[snip]
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));
}
Do something like
void someRoutine( BigFloat const& a )
{
// some operation on "a"
}
If "some operation" fails it will throw an exception.
What if the operation though is something that returns
an error value instead?

The you convert to exception.

I could, but I need to send the value of that
pointer in a generic 32-bit integer variable.
Fair warning: code below is my preferred way but many programmers find
it unnatural. If you find it unnatural, just replace "||" with "if".

bool throwX( char const s[] ) { throw std::runtime_error( s ); }

void someRoutine( BigFloat const& a )
{
someOp( a ) == NO_ERROR || throwX( "someRoutine: someOp failed" );
}
Oh and when I throw the exception
I also need to convert a pointer to give additional
information to whatever handler catches the exception,
(there's handlers in any area where exceptions may
get thrown out of) for example to show that an
operation on "a" failed.

That seems to a requirement that stems from a particular current
solution. When replacing the current solution the requirement then
disappears.

So then just don't tell what the "offending" operand
was, right? Or invent some ad hoc coding scheme?
I don't like those as I find them hard to maintain.
Personal preference. There is a run-time cost associated with throwing
exceptions, and that needs to be weighted against clarity and ease of
programming: running time versus programmer's time and correctness. But
in general, as long as the program is fast enough, exceptions are in my
experience preferable even when the situation is not "exceptional".
However, it's /very important/ to think about simplicity of /usage/.
For if using the function will then require a try/catch in the immediate
caller for the most common usage, then exceptions are strongly
contra-indicated -- most try/catch-es indicate a possible improvement.

OK. See, that's the thing I try to do. I throw exceptions
where they're needed, like if operator "+" fails, or the
constructor fails, or something, but for other things like
a casual call to reset coordinates for a zoom, I go
and return error codes, to avoid the expensive and
ugly-looking "try...catch" blocks everywhere.

PS. The program is _not_ fast enough right now, but I'm not
going to bother optimizing it now since I want to get it to
a well-working and _stable_ version first.
[snip]
So then you have to typecast, right?
Nope.

OK.

(No typecasting)

This is good, but perhaps even better:

double doubleDiv( int a, int b ) { return 1.0*a/b; }

For some reason I like one-liners... :)

Any half-decent compiler should optimize away the "1.0*". What it does
is to force a promotion to double of a and b. Before anything else.

Alright.
[snip]

It works now! The bug has been fixed!
Good.

Yep.
The Init functions are *pnly* and I say again, *ONLY*
called in CONSTRUCTORS, period. And *always* called from
them. They're just there to save a bit of cutting-and-
pasting. At no point are they called anywhere else.

By expressing them as constructors (of e.g. a private base class) you
express that in code, /ensuring/ that they're not called from anywhere
else, and so making it completely safe to remove initialization checks.

So then would making the code explicit, even though
it's repetitive and looks ugly, in the BigFloat()
constructors be a good idea?
[snip]
Could you tell me where my design is wanting, by the way?
I'd like to know so I can improve it.

Please note first that /every/ design is wanting.

There is no such thing as a prefetc design.

I know, I didn't say there was.
So the question is where to draw the line of possible improvement versus
work.

That's right.
Since the present design is causing trouble, that line is not yet reached.

I'd start by a physical repackaging, not design. Currently, 'main.h'
(or something) is included everywhere, and a module's implementation
does not include the module's own header file. That should be exactly
opposite, for a great number of reasons, one of which is that currently
any change of 'main.h' forces a recompilation of (nearly) everything.

So then is it OK to include all the external library headers
again and again without an easy reference file like main.h?
The main design problem I saw, with just a cursory look at the code, was
a mix of very high level (abstract operations) and low level (pointers,
casting), an abstraction gap, indicating one or more missing
intermediate levels.

Try to encapsulate low-level operations in some not-very-high-level
classes. For example, such encapsulation classes, or functions, do all
pointer stuff, translate from error codes to exceptions, etc. Just
getting that bug-inducing low level stuff /out of the way/, packaged.

What exactly would it be a good idea to encapsulate, anyway?
Like how would one encapuslate all the pointer stuff, anyway?
There's one place where I need to manipulate the pointers
low-level directly for speed, and that's in that tiny amount
of core routines used for computing the fractals with bignum
arithmetic (the "FastXXXX" bignum routines that are called
in the tight inner loops of the fractal formulas. In that
case, a call to a "pointer class"'s member functions would
eat time like crazy since those arithmetic routines are being
called millions of times. Extra function calls for every
pointer manipulation would just add too much cost there.).
But outside of that, what would I do?

Is this an example of the type of mixed abstraction you
were talking about?:

---
void SomeFunction(int something)
{
FG3DError err;

<blah blah blah>

if(<something goes wrong>) throw Exception(err.dwErrCode,
err.dwAdditionalInformation);

<blah blah blah>
}
---

which accesses the members of "err" directly,
versus

---
void SomeFunction(int something)
{
FG3DError err;

<blah blah blah>

if(<something goes wrong>) throw Exception(err);

<blah blah blah>
}
---

which doesn't?

Else-thread I have already mentioned another aspect of that high level
low level clash, that it would be a good idea to use std::vector instead
of raw arrays and pointers.

I'll give that a try and see what happens.
I think the above is the most important. But since no design is
prefetc, having done this other possibilities (including replacing
Init-functions with constructors, if not yet done) will suggest
themselves. The important thing then is to be very aware of whether the
improvements fix current bugs, prevent future ones, help future
maintainance, help reuse, or what. If the gain is not clear, but is
just "feels more elegant", then possibly the line has been reached.

[snip]
Signature snipped.

Ah, thanks.

You're welcome.
 
L

LR

Alf said:
Try to encapsulate low-level operations in some not-very-high-level
classes. For example, such encapsulation classes, or functions, do all
pointer stuff, translate from error codes to exceptions, etc. Just
getting that bug-inducing low level stuff /out of the way/, packaged.

Else-thread I have already mentioned another aspect of that high level
low level clash, that it would be a good idea to use std::vector instead
of raw arrays and pointers.

And don't over look the ease of use issues, for example, want to set all
the elements of a std::vector<int> to zero?

std::vector<int> t;
// ...more code here...
t.assign(t.size(),0);

I'd like to add that getting rid of all, or at least as much as you can,
the manipulation of char arrays and pointers by using std::string
instead might go some way to reducing work. String streams can be
pretty useful along those lines too.

Sure, the buffers you create are probably, most likely, expected to be,
big enough. But then you'll discover to your sorrow that they weren't.
Annoying that.

Also, I find that some simple things make code easier to deal with.

For example, if I have a function
void f(const int a);
that gets called a few dozen times with double, like so:
f((int)1.3); // or something
it's easier to just add another function (or ctor, or method, with
appropriate syntax accordingly) like
void f(const double a);
rather than doing all those casts, even if the second calls the first.
That'll still look a little cleaner.

And I'd like to repeat what has been already mentioned. Be careful with
those casts. Particularly with casting pointers to an integral type or
vice-versa, in general this is not wise.

LR
 
M

mike3


Cool. What is it called, anyway?
Not as far as I know, but unless it's very different from 7.1 you can
use the command line tools separately from the IDE.

Where can I get it, anyway?






[snip]
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));
}
Do something like
void someRoutine( BigFloat const& a )
{
// some operation on "a"
}
If "some operation" fails it will throw an exception.
What if the operation though is something that returns
an error value instead?
The you convert to exception.

I could, but I need to send the value of that
pointer in a generic 32-bit integer variable.




Fair warning: code below is my preferred way but many programmers find
it unnatural. If you find it unnatural, just replace "||" with "if".
bool throwX( char const s[] ) { throw std::runtime_error( s ); }
void someRoutine( BigFloat const& a )
{
someOp( a ) == NO_ERROR || throwX( "someRoutine: someOp failed" );
}
That seems to a requirement that stems from a particular current
solution. When replacing the current solution the requirement then
disappears.

So then just don't tell what the "offending" operand
was, right? Or invent some ad hoc coding scheme?
I don't like those as I find them hard to maintain.




Personal preference. There is a run-time cost associated with throwing
exceptions, and that needs to be weighted against clarity and ease of
programming: running time versus programmer's time and correctness. But
in general, as long as the program is fast enough, exceptions are in my
experience preferable even when the situation is not "exceptional".
However, it's /very important/ to think about simplicity of /usage/.
For if using the function will then require a try/catch in the immediate
caller for the most common usage, then exceptions are strongly
contra-indicated -- most try/catch-es indicate a possible improvement.

OK. See, that's the thing I try to do. I throw exceptions
where they're needed, like if operator "+" fails, or the
constructor fails, or something, but for other things like
a casual call to reset coordinates for a zoom, I go
and return error codes, to avoid the expensive and
ugly-looking "try...catch" blocks everywhere.

PS. The program is _not_ fast enough right now, but I'm not
going to bother optimizing it now since I want to get it to
a well-working and _stable_ version first.
[snip]
Will this give the full "long" result
No, in the code you showed the arguments would be promoted to int, the
computation done as int, and only then the result converted to long.
So then you have to typecast, right?

OK.

(No typecasting)
This is good, but perhaps even better:
double doubleDiv( int a, int b ) { return 1.0*a/b; }
For some reason I like one-liners... :)
Any half-decent compiler should optimize away the "1.0*". What it does
is to force a promotion to double of a and b. Before anything else.
Alright.
It works now! The bug has been fixed!

Yep.
The Init functions are *pnly* and I say again, *ONLY*
called in CONSTRUCTORS, period. And *always* called from
them. They're just there to save a bit of cutting-and-
pasting. At no point are they called anywhere else.
By expressing them as constructors (of e.g. a private base class) you
express that in code, /ensuring/ that they're not called from anywhere
else, and so making it completely safe to remove initialization checks.

So then would making the code explicit, even though
it's repetitive and looks ugly, in the BigFloat()
constructors be a good idea?
[snip]
Could you tell me where my design is wanting, by the way?
I'd like to know so I can improve it.
Please note first that /every/ design is wanting.
There is no such thing as a prefetc design.

I know, I didn't say there was.
So the question is where to draw the line of possible improvement versus
work.

That's right.
Since the present design is causing trouble, that line is not yet reached.
I'd start by a physical repackaging, not design. Currently, 'main.h'
(or something) is included everywhere, and a module's implementation
does not include the module's own header file. That should be exactly
opposite, for a great number of reasons, one of which is that currently
any change of 'main.h' forces a recompilation of (nearly) everything.

So then is it OK to include all the external library headers
again and again without an easy reference file like main.h?
The main design problem I saw, with just a cursory look at the code, was
a mix of very high level (abstract operations) and low level (pointers,
casting), an abstraction gap, indicating one or more missing
intermediate levels.
Try to encapsulate low-level operations in some not-very-high-level
classes. For example, such encapsulation classes, or functions, do all
pointer stuff, translate from error codes to exceptions, etc. Just
getting that bug-inducing low level stuff /out of the way/, packaged.

What exactly would it be a good idea to encapsulate, anyway?
Like how would one encapuslate all the pointer stuff, anyway?
There's one place where I need to manipulate the pointers
low-level directly for speed, and that's in that tiny amount
of core routines used for computing the fractals with bignum
arithmetic (the "FastXXXX" bignum routines that are called
in the tight inner loops of the fractal formulas. In that
case, a call to a "pointer class"'s member functions would
eat time like crazy since those arithmetic routines are being
called millions of times. Extra function calls for every
pointer manipulation would just add too much cost there.).
But outside of that, what would I do?

Is this an example of the type of mixed abstraction you
were talking about?:

---
void SomeFunction(int something)
{
FG3DError err;

<blah blah blah>

if(<something goes wrong>) throw Exception(err.dwErrCode,
err.dwAdditionalInformation);

<blah blah blah>}

---

which accesses the members of "err" directly,
versus

---
void SomeFunction(int something)
{
FG3DError err;

<blah blah blah>

if(<something goes wrong>) throw Exception(err);

<blah blah blah>}

---

which doesn't?
Else-thread I have already mentioned another aspect of that high level
low level clash, that it would be a good idea to use std::vector instead
of raw arrays and pointers.

I'll give that a try and see what happens.
I think the above is the most important. But since no design is
prefetc, having done this other possibilities (including replacing
Init-functions with constructors, if not yet done) will suggest
themselves. The important thing then is to be very aware of whether the
improvements fix current bugs, prevent future ones, help future
maintainance, help reuse, or what. If the gain is not clear, but is
just "feels more elegant", then possibly the line has been reached.
Signature snipped.
Ah, thanks.

You're welcome.


Cheers, & hth.,

Any answers or comments yet?
 
M

mike3

I still haven't heard any response yet.

But I would still really want to know what exactly to do
with improving the design. You suggested that I try
to add in "intermediate" levels of abstraction, with
low level classes to handle pointers, etc. Wouldn't I
then need to set up a class for each and every data type
I want to make an array? Or would using std::vector, etc.
be acceptable?

Would it be a good idea to, for example, with the BigFloat
thing, encapsulate the digits and all that into a separate
"RawInt" class that is essentially an integer type, from
which BigFloat would be made a derived class? This would
help get rid of the nasty Init functions that I heard were
such a bad idea (since even if their use is limited to
constructors, it is still possible one may accidentally
slip and call them from somewhere else), since then each
constructor for the different varieties of BigFloat would
not need those to initialize the digit array as that's
taken care of by RawInt's constructor. And the RawInt
routines would be able to do arithmetic of parts of the
RawInts to other parts, so that all the "pointer gymnastics"
seen in the floating point routines would be handled by
the lower-level RawInt, and then finally through the
safer and better std::vector arrays.

That would reorganize it to something like

class RawInt
{
protected:
std::vector<DIGIT> digits; <--- note the use of std::vector!
int length;
public:
RawInt();
~RawInt();
<everything in rawint.cpp remade into member
functions, reworked to handle disparate lengths,
etc.>
}

and

class BigFloat : private RawInt
{
private:
u32 signexp; /* sign-exponent combination */
public:
<everything in bigfloat.cpp, etc.>
}

..

(and reworking all the arithmetic stuff appropriately,
of course.)

Does that sound like a good idea? I've already started
doing it since it looks good to me.

PS. I've also changed all instances of "DIGIT32" to
"DIGIT" in the full program in case I want to make
a 64-bit version for 64-bit processors when I get one,
and reworked it a bit so that 32-bit-specific things
have been turned into a few macros and defines that
can be easily changed to resize the digit being
used.
 
M

mike3

I'm not sure what the requirements you're trying to achieve.

If you read some of the earlier messages here you can see
what I was going after. I got a suggestion that the design
I had was more prone to having bugs, since it had an
"abstraction gap" with "mixing" low and high level stuff.
 
M

mike3

If you read some of the earlier messages here you can see
what I was going after. I got a suggestion that the design
I had was more prone to having bugs, since it had an
"abstraction gap" with "mixing" low and high level stuff.

Any comment?
 
G

Gianni Mariani

mike3 said:

I didn't go through all the postings to divine your requirements. I
probably won't have the time or desire to do that for you. If you'd
like me to look at it (or anyone else for that matter), I'd suggest
making it as easy as possible for them to understand what you're trying
to do.
 
M

mike3

I didn't go through all the postings to divine your requirements. I
probably won't have the time or desire to do that for you. If you'd
like me to look at it (or anyone else for that matter), I'd suggest
making it as easy as possible for them to understand what you're trying
to do.

I explained briefly what it is, in my own posting above.
One of the people here said the program had an
"abstraction gap", in which it was said there was a
wide difference between high levels of abstraction like
bignums, and low levels like pointers and casting, and
it was suggested that I encapsulate pointers, and
coverting errors to exceptions, and other low level
stuff (which was not specified), into a set of low
level classes and functions. So what I was trying to do
here was smooth that gap out a bit. The reason for
this being objectionable is not that it *contains*
bugs, but that it is *prone* to bugs, which makes
the software harder to maintain.

If want to to read that post, and that one alone, without
hunting through the thread, here is a straight link to it:

http://groups.google.com/group/comp.lang.c++/msg/a66278b77597d648

Here's a quote:

"Try to encapsulate low-level operations in some not-very-high-level
classes. For example, such encapsulation classes, or functions, do
all
pointer stuff, translate from error codes to exceptions, etc. Just
getting that bug-inducing low level stuff /out of the way/, packaged.


Else-thread I have already mentioned another aspect of that high
level
low level clash, that it would be a good idea to use std::vector
instead
of raw arrays and pointers. "

So therefore what I was trying to do with my program was
to replace the slew of "raw integer" routines with a RawInt
class, and use std::vector<> for arrays/pointers. This
std::vector<> would then initialize/free the memory for
the digits, eliminating the need for "Init" functions that
were said to be bad since there's no way to guarantee you
might not use them out of negligence is places where
they should not be used, even if intended to be called only
from constructors. In addition, I think it would smooth
that gap I mentioned to some degree. As then instead of
having this:

direct arrays < BigFloat

we have

direct arrays < std::vector < RawInt < BigFloat.

Does this help?
 
M

mike3

I explained briefly what it is, in my own posting above.
One of the people here said the program had an
"abstraction gap", in which it was said there was a
wide difference between high levels of abstraction like
bignums, and low levels like pointers and casting, and
it was suggested that I encapsulate pointers, and
coverting errors to exceptions, and other low level
stuff (which was not specified), into a set of low
level classes and functions. So what I was trying to do
here was smooth that gap out a bit. The reason for
this being objectionable is not that it *contains*
bugs, but that it is *prone* to bugs, which makes
the software harder to maintain.

If want to to read that post, and that one alone, without
hunting through the thread, here is a straight link to it:

http://groups.google.com/group/comp.lang.c++/msg/a66278b77597d648

Here's a quote:

"Try to encapsulate low-level operations in some not-very-high-level
classes. For example, such encapsulation classes, or functions, do
all
pointer stuff, translate from error codes to exceptions, etc. Just
getting that bug-inducing low level stuff /out of the way/, packaged.

Else-thread I have already mentioned another aspect of that high
level
low level clash, that it would be a good idea to use std::vector
instead
of raw arrays and pointers. "

So therefore what I was trying to do with my program was
to replace the slew of "raw integer" routines with a RawInt
class, and use std::vector<> for arrays/pointers. This
std::vector<> would then initialize/free the memory for
the digits, eliminating the need for "Init" functions that
were said to be bad since there's no way to guarantee you
might not use them out of negligence is places where
they should not be used, even if intended to be called only
from constructors. In addition, I think it would smooth
that gap I mentioned to some degree. As then instead of
having this:

direct arrays < BigFloat

we have

direct arrays < std::vector < RawInt < BigFloat.

Does this help?

Did you get my post?
 
M

mike3

I explained briefly what it is, in my own posting above.
One of the people here said the program had an
"abstraction gap", in which it was said there was a
wide difference between high levels of abstraction like
bignums, and low levels like pointers and casting, and
it was suggested that I encapsulate pointers, and
coverting errors to exceptions, and other low level
stuff (which was not specified), into a set of low
level classes and functions. So what I was trying to do
here was smooth that gap out a bit. The reason for
this being objectionable is not that it *contains*
bugs, but that it is *prone* to bugs, which makes
the software harder to maintain.

If want to to read that post, and that one alone, without
hunting through the thread, here is a straight link to it:

http://groups.google.com/group/comp.lang.c++/msg/a66278b77597d648

Here's a quote:

"Try to encapsulate low-level operations in some not-very-high-level
classes. For example, such encapsulation classes, or functions, do
all
pointer stuff, translate from error codes to exceptions, etc. Just
getting that bug-inducing low level stuff /out of the way/, packaged.

Else-thread I have already mentioned another aspect of that high
level
low level clash, that it would be a good idea to use std::vector
instead
of raw arrays and pointers. "

So therefore what I was trying to do with my program was
to replace the slew of "raw integer" routines with a RawInt
class, and use std::vector<> for arrays/pointers. This
std::vector<> would then initialize/free the memory for
the digits, eliminating the need for "Init" functions that
were said to be bad since there's no way to guarantee you
might not use them out of negligence is places where
they should not be used, even if intended to be called only
from constructors. In addition, I think it would smooth
that gap I mentioned to some degree. As then instead of
having this:

direct arrays < BigFloat

we have

direct arrays < std::vector < RawInt < BigFloat.

Does this help?

Any response?
 
M

mike3

I explained briefly what it is, in my own posting above.
One of the people here said the program had an
"abstraction gap", in which it was said there was a
wide difference between high levels of abstraction like
bignums, and low levels like pointers and casting, and
it was suggested that I encapsulate pointers, and
coverting errors to exceptions, and other low level
stuff (which was not specified), into a set of low
level classes and functions. So what I was trying to do
here was smooth that gap out a bit. The reason for
this being objectionable is not that it *contains*
bugs, but that it is *prone* to bugs, which makes
the software harder to maintain.

If want to to read that post, and that one alone, without
hunting through the thread, here is a straight link to it:

http://groups.google.com/group/comp.lang.c++/msg/a66278b77597d648

Here's a quote:

"Try to encapsulate low-level operations in some not-very-high-level
classes. For example, such encapsulation classes, or functions, do
all
pointer stuff, translate from error codes to exceptions, etc. Just
getting that bug-inducing low level stuff /out of the way/, packaged.

Else-thread I have already mentioned another aspect of that high
level
low level clash, that it would be a good idea to use std::vector
instead
of raw arrays and pointers. "

So therefore what I was trying to do with my program was
to replace the slew of "raw integer" routines with a RawInt
class, and use std::vector<> for arrays/pointers. This
std::vector<> would then initialize/free the memory for
the digits, eliminating the need for "Init" functions that
were said to be bad since there's no way to guarantee you
might not use them out of negligence is places where
they should not be used, even if intended to be called only
from constructors. In addition, I think it would smooth
that gap I mentioned to some degree. As then instead of
having this:

direct arrays < BigFloat

we have

direct arrays < std::vector < RawInt < BigFloat.

Does this help?

No comments yet?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,160
Latest member
CollinStri
Top