Jump to page: 1 26  
Page
Thread overview
Writing Bug-Free C/D Code
Mar 19, 2007
Knud Soerensen
Mar 19, 2007
Henning Hasemann
Mar 19, 2007
Thomas Kuehne
Mar 19, 2007
Henning Hasemann
Mar 19, 2007
Thomas Kuehne
Mar 19, 2007
Henning Hasemann
Mar 19, 2007
Luís Marques
Mar 19, 2007
Frits van Bommel
Mar 19, 2007
Sean Kelly
Mar 19, 2007
Daniel Keep
Mar 19, 2007
Henning Hasemann
Mar 19, 2007
Daniel Keep
Mar 19, 2007
Knud Soerensen
Mar 19, 2007
Henning Hasemann
Mar 19, 2007
Knud Soerensen
Mar 20, 2007
David B. Held
Mar 20, 2007
Daniel Keep
Mar 20, 2007
Sean Kelly
Mar 20, 2007
Manfred Nowak
Mar 20, 2007
Derek Parnell
Mar 20, 2007
David B. Held
Mar 20, 2007
Derek Parnell
Mar 21, 2007
David B. Held
Mar 21, 2007
Derek Parnell
Mar 21, 2007
Dan
Mar 21, 2007
Derek Parnell
Mar 21, 2007
Sean Kelly
Mar 21, 2007
Dan
Mar 21, 2007
Sean Kelly
Mar 21, 2007
Derek Parnell
Mar 22, 2007
Sean Kelly
Mar 22, 2007
Derek Parnell
Mar 22, 2007
Dan
Mar 23, 2007
Derek Parnell
templatizing parameters and induction (was Re: Writing Bug-Free C/D Code)
Mar 23, 2007
Kevin Bealer
Mar 23, 2007
David B. Held
Mar 23, 2007
David B. Held
Mar 23, 2007
Daniel Keep
Mar 23, 2007
David B. Held
Re: templatizing parameters and induction (was Re: Writing Bug-Free
Mar 23, 2007
Dan
Mar 23, 2007
Reiner Pope
Mar 23, 2007
Don Clugston
Mar 23, 2007
Reiner Pope
Mar 19, 2007
janderson
Mar 19, 2007
BCS
Mar 21, 2007
Jascha Wetzel
Mar 21, 2007
Knud Soerensen
Mar 21, 2007
Sean Kelly
March 19, 2007
This morning I stumbled over a on-line book named "Writing Bug-Free C Code"
http://www.duckware.com/bugfreec/index.html
the gem of the book (chapter 4) is a way to implement an object model which
provide better data hiding than C++ classes.

It also gives advise like:
"Use a debugger only as a last resort. Having to resort to a debugger means
your programming methodologies have failed."
and
"When fixing a bug, fix the underlying problem or cause of the bug and not just the bug itself."

D already have many feature which help the programmer make lesser bugs, but how can we make it even better ?

I think a good place to start is look at the last bugs reported by the users in released D programs, and consider if it is coursed by some fundamental flaw in D and what can be done to catch it earlier in development.

Maybe we need a place to report and discus this type of bugs.
Is the newsgroup okay or would a bug-tracking system be a better option ?
March 19, 2007
I just start a few little things.

1.)
Most of the bugs I had when starting with D where that I simply forgot
to initialise members in the c'tor:

class Foo {
  void foo() { ... };
}

class Bar {
  Foo myFoo;
  void bar() {
    myFoo.foo();
  }
}

Of course, because here myFoo is default initialised to null this always gives
a segfault where myFoo is first being used in such a way,
so it is very easy to track down (if you use a debugger at least).

But sometimes I'd find it nice if there was a way to tell D:
Warn me at compile time if it is clear that some class instance members
will be null.

Of course you must be able to tell D exceptions to this, as you will want to have a few members be null until later.

I have no good idea what this tool would syntactically look like or if it would make sense to have it a compiler switch or whatever. Probably the idea is almost bullsh*t nevertheless, because you get used to initialise your members after a short while.

2.)
Another thing would be easy support for stack traced exceptions.
I tried flectioned last weak or so (just for this purpose) but it
didnt want to compile with my code (I think I was still on dmd-1.007 so
it might have been a bug there). I think STE's are of use
to many developers so they should be put into phobos or so.

3.)
Please change the implicit integral casting rules to be more c-like.
This has been discussed here and I cant remember a good argument
against casting only in such a way data doesnt get lost.
(ie: int->float is okay, but float->int, or int->uint is not)
I had errors that where very hard to track down, because somthing like
(-1 * 4u) yields the unsigned int representation of -4 which is
4294967292, which is rather unintuitive when there is no explicit cast.

I know, changing this might break some code, but I cant help considering code that relies on such implicit casting rules broken nevertheless.

Henning

-- 
v4sw7Yhw4ln0pr7Ock2/3ma7uLw5Xm0l6/7DGKi2e6t6ELNSTVXb7AHIMOen5a2Xs5Mr2g5ACPR hackerkey.com
March 19, 2007
Henning Hasemann schrieb am 2007-03-19:

<snip>

> 2.)
> Another thing would be easy support for stack traced exceptions.
> I tried flectioned last weak or so (just for this purpose) but it
> didnt want to compile with my code (I think I was still on dmd-1.007 so
> it might have been a bug there). I think STE's are of use
> to many developers so they should be put into phobos or so.

Exactly what problems did you encounter?

Thomas


March 19, 2007

Henning Hasemann wrote:
> I just start a few little things.
> 
> 1.)
> Most of the bugs I had when starting with D where that I simply forgot
> to initialise members in the c'tor:
> 
> class Foo {
>   void foo() { ... };
> }
> 
> class Bar {
>   Foo myFoo;
>   void bar() {
>     myFoo.foo();
>   }
> }
> 
> Of course, because here myFoo is default initialised to null this always gives
> a segfault where myFoo is first being used in such a way,
> so it is very easy to track down (if you use a debugger at least).
> 
> But sometimes I'd find it nice if there was a way to tell D:
> Warn me at compile time if it is clear that some class instance members
> will be null.
> 
> Of course you must be able to tell D exceptions to this, as you will want to have a few members be null until later.
> 
> I have no good idea what this tool would syntactically look like or if it would make sense to have it a compiler switch or whatever. Probably the idea is almost bullsh*t nevertheless, because you get used to initialise your members after a short while.

You do get used to it, and you're right: how exactly could a tool tell the difference between "accidentally null" and "deliberately null"?

I've found, actually, that with type inference I almost never get this
problem.  Nowadays, I instinctively write the above as "auto myFoo = new
Foo;".  If I get to the end of the line, and haven't actually mentioned
a type anywhere, that's a good signal I've forgotten something :P  It
also helps that you can't declare an auto variable without initialising it.

> 2.)
> Another thing would be easy support for stack traced exceptions.
> I tried flectioned last weak or so (just for this purpose) but it
> didnt want to compile with my code (I think I was still on dmd-1.007 so
> it might have been a bug there). I think STE's are of use
> to many developers so they should be put into phobos or so.

I agree that more informative exceptions would be fantastic.

> 3.)
> Please change the implicit integral casting rules to be more c-like.
> This has been discussed here and I cant remember a good argument
> against casting only in such a way data doesnt get lost.
> (ie: int->float is okay, but float->int, or int->uint is not)
> I had errors that where very hard to track down, because somthing like
> (-1 * 4u) yields the unsigned int representation of -4 which is
> 4294967292, which is rather unintuitive when there is no explicit cast.

It's unintuitive because you're asking the compiler to perform a nonsensical operation: multiplication between two partially disjoint sets.

It's a bit like complaining that (3 * "2") doesn't work in D.  In PHP, it results in 6, in Python, it results in "222".  Which one's right?

> I know, changing this might break some code, but I cant help considering code that relies on such implicit casting rules broken nevertheless.

This is, in my opinion, a really bad idea.  You're basically saying that the compiler should never complain if an operation *destroys data*. What's more, it's these sorts of destructive implicit casts that are very difficult to track down.

The root problem here is that you're trying to mix signed and unsigned operations together, and expecting a signed result.  My personal rule of thumb is: never, ever get signed/unsigned types within five kilometres of each other.  If you think something is signed, but aren't sure, assert it!

I actually think a better solution would be to add an Integer type to D: one that actually, really, truly works like an integer, and not a member of Z_{2^32} :P

> Henning
> 

	-- Daniel

-- 
Unlike Knuth, I have neither proven or tried the above; it may not even make sense.

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
March 19, 2007
Henning Hasemann wrote:
> I just start a few little things.
> 
> 1.)
> Most of the bugs I had when starting with D where that I simply forgot
> to initialise members in the c'tor:
> 
> class Foo {
>   void foo() { ... };
> }
> 
> class Bar {
>   Foo myFoo;
>   void bar() {
>     myFoo.foo();
>   }
> }
> 
> Of course, because here myFoo is default initialised to null this always gives
> a segfault where myFoo is first being used in such a way,
> so it is very easy to track down (if you use a debugger at least).
> 
> But sometimes I'd find it nice if there was a way to tell D:
> Warn me at compile time if it is clear that some class instance members
> will be null.
> 
> Of course you must be able to tell D exceptions to this, as you will want
> to have a few members be null until later.
> 
> I have no good idea what this tool would syntactically look like or
> if it would make sense to have it a compiler switch or whatever.
> Probably the idea is almost bullsh*t nevertheless, because you get
> used to initialise your members after a short while.

C# will warn you if a variable is private and never used or never initialized.  Some C++ versions have warnings (which I always set as errors) that tells you if a variable in a function is never initialized.

That's a start at least.  Perhaps D could do the same.  In effect the private keyword becomes the checker for you.

[snip]

> 3.)
> Please change the implicit integral casting rules to be more c-like.
> This has been discussed here and I cant remember a good argument
> against casting only in such a way data doesnt get lost.
> (ie: int->float is okay, but float->int, or int->uint is not)
> I had errors that where very hard to track down, because somthing like
> (-1 * 4u) yields the unsigned int representation of -4 which is
> 4294967292, which is rather unintuitive when there is no explicit cast.

int->float, I don't agree this is ok however int->double is in my books.  Anything that has potential for data loss, you should have to explicitly cast.

I generally agree though.

> 
> I know, changing this might break some code, but I cant help considering
> code that relies on such implicit casting rules broken nevertheless.

Agreed.

> Henning
> 
March 19, 2007
On Mon, 19 Mar 2007 19:46:50 +1100
Daniel Keep <daniel.keep.lists@gmail.com> wrote:

> It's unintuitive because you're asking the compiler to perform a nonsensical operation: multiplication between two partially disjoint sets.

You are right with this: Neither int nor uint are a good default type to
convert to here.
But when I compile with -w where I get a warning when putting an int
into a short, I want to somehow get warned here that the meaning of
the - sign may get reinterpreted, or better said:
That the result of this operation is implicitly casted to a type
which is not capable of representing it without loss of data
or in this case meaning (as actually no bit gets lost).

This can be very hard to track down if you have such things with variables.
Say you are mocking around with SDL and take a width of some thing
and calculating arounds with ints (width * negative value *can* be a useful
value). If your calculation is long/complex enough it'll take some time finding this.

> It's a bit like complaining that (3 * "2") doesn't work in D.  In PHP, it results in 6, in Python, it results in "222".  Which one's right?

Yeah right, but as you mentioned, D doesnt *allow* this instead of returning one of the questionable results.

> > I know, changing this might break some code, but I cant help considering code that relies on such implicit casting rules broken nevertheless.
> 
> This is, in my opinion, a really bad idea.  You're basically saying that the compiler should never complain if an operation *destroys data*.

Now. I say it should either implicitly cast so it doesnt destroy data
(ie float * int = float etc...), or complain when it has to destroy data.
In the example -2 * 3u at least meaning is changed without any complaint.
I *do not* say this should be an int.
This should be either implicicly a long (which would be capable of
representing all results from int * uint) or at least some warning
when compiling with -w.

But I must confess, after writing all the things above I tested around
a bit again and saw: Implicit conversions other than the int * uint case,
such as int * float do what I would expect.
The int * uint thing got me so screwed in the past I casted everything
manually because I feared D could do something evil ,-)


> The root problem here is that you're trying to mix signed and unsigned operations together, and expecting a signed result.  My personal rule of thumb is: never, ever get signed/unsigned types within five kilometres of each other.  If you think something is signed, but aren't sure, assert it!

I sometimes have some problems with this, as said before: Let SDL return
a width as uint and have your positions int (because they also can be negative).

I had this problems with C already. Examples of questions I have often when coding:
- "Hmm okay. You're a on-screen coordinate. You will be positive.
  But I might to want to mix you with virtual and potetially negative
  Coordinates. Also you wont be larger than 32000, as long as screens
  wont get really big. But I somehow feel I should make you an int..."
- Hm okay so I have these few things I know of they wont be negative.
  Should I make them int nevertheless? Would avoid complications and warinings,
  and the value range wouldnt be a problem.

> I actually think a better solution would be to add an Integer type to D: one that actually, really, truly works like an integer, and not a member of Z_{2^32} :P

Yeah, like the python one. Should not be too hard to implement I guess.

Henning

-- 
v4sw7Yhw4ln0pr7Ock2/3ma7uLw5Xm0l6/7DGKi2e6t6ELNSTVXb7AHIMOen5a2Xs5Mr2g5ACPR hackerkey.com
March 19, 2007
On Mon, 19 Mar 2007 08:41:48 +0000 (UTC)
Thomas Kuehne <thomas-dloop@kuehne.cn> wrote:

> 
> > 2.)
> > Another thing would be easy support for stack traced exceptions.
> > I tried flectioned last weak or so (just for this purpose) but it
> > didnt want to compile with my code (I think I was still on dmd-1.007 so
> > it might have been a bug there). I think STE's are of use
> > to many developers so they should be put into phobos or so.
> 
> Exactly what problems did you encounter?

It does not correctly recognise that I'm on phobos I guess because when compiling I get:

flectioned.d(78): module Vararg cannot read file 'tango/core/Vararg.d'

I use dmd-1.009 and rebuild-0.12 for compiling. OS is linux.
dmd -c flectioned.d runs fine, so maybe rebuild is the real problem?

Henning

-- 
v4sw7Yhw4ln0pr7Ock2/3ma7uLw5Xm0l6/7DGKi2e6t6ELNSTVXb7AHIMOen5a2Xs5Mr2g5ACPR hackerkey.com
March 19, 2007
Henning Hasemann schrieb am 2007-03-19:
> On Mon, 19 Mar 2007 08:41:48 +0000 (UTC)
> Thomas Kuehne <thomas-dloop@kuehne.cn> wrote:
>
>> 
>> > 2.)
>> > Another thing would be easy support for stack traced exceptions.
>> > I tried flectioned last weak or so (just for this purpose) but it
>> > didnt want to compile with my code (I think I was still on dmd-1.007 so
>> > it might have been a bug there). I think STE's are of use
>> > to many developers so they should be put into phobos or so.
>> 
>> Exactly what problems did you encounter?
>
> It does not correctly recognise that I'm on phobos I guess because when compiling I get:
>
> flectioned.d(78): module Vararg cannot read file 'tango/core/Vararg.d'
>
> I use dmd-1.009 and rebuild-0.12 for compiling. OS is linux.
> dmd -c flectioned.d runs fine, so maybe rebuild is the real problem?

Do you use the original Phobos?

Line 65 checks if Object.toUtf8 is defined wich would indicate that Tango is installed. Failing to import tango.core.Vararg however indicates that Tango isn't installed.

Thomas

March 19, 2007
Henning Hasemann wrote:
> On Mon, 19 Mar 2007 08:41:48 +0000 (UTC)
> Thomas Kuehne <thomas-dloop@kuehne.cn> wrote:
> 
>>> 2.)
>>> Another thing would be easy support for stack traced exceptions.
>>> I tried flectioned last weak or so (just for this purpose) but it
>>> didnt want to compile with my code (I think I was still on dmd-1.007 so
>>> it might have been a bug there). I think STE's are of use
>>> to many developers so they should be put into phobos or so.
>> Exactly what problems did you encounter?
> 
> It does not correctly recognise that I'm on phobos I guess because
> when compiling I get:
> 
> flectioned.d(78): module Vararg cannot read file 'tango/core/Vararg.d'
> 
> I use dmd-1.009 and rebuild-0.12 for compiling. OS is linux.
> dmd -c flectioned.d runs fine, so maybe rebuild is the real problem?

That module should only be imported if Object has a method toUtf8(), which in Phobos it doesn't. Check your import paths, and make sure you're using the right object.d[i].
March 19, 2007

Henning Hasemann wrote:
> On Mon, 19 Mar 2007 19:46:50 +1100
> Daniel Keep <daniel.keep.lists@gmail.com> wrote:
> 
>> It's unintuitive because you're asking the compiler to perform a nonsensical operation: multiplication between two partially disjoint sets.
> 
> You are right with this: Neither int nor uint are a good default type to
> convert to here.
> But when I compile with -w where I get a warning when putting an int
> into a short, I want to somehow get warned here that the meaning of
> the - sign may get reinterpreted, or better said:
> That the result of this operation is implicitly casted to a type
> which is not capable of representing it without loss of data
> or in this case meaning (as actually no bit gets lost).
> 
> This can be very hard to track down if you have such things with variables.
> Say you are mocking around with SDL and take a width of some thing
> and calculating arounds with ints (width * negative value *can* be a useful
> value). If your calculation is long/complex enough it'll take some time finding this.
> 
>> It's a bit like complaining that (3 * "2") doesn't work in D.  In PHP, it results in 6, in Python, it results in "222".  Which one's right?
> 
> Yeah right, but as you mentioned, D doesnt *allow* this instead of returning one of the questionable results.
> 
>>> I know, changing this might break some code, but I cant help considering code that relies on such implicit casting rules broken nevertheless.
>> This is, in my opinion, a really bad idea.  You're basically saying that the compiler should never complain if an operation *destroys data*.
> 
> Now. I say it should either implicitly cast so it doesnt destroy data
> (ie float * int = float etc...), or complain when it has to destroy data.
> In the example -2 * 3u at least meaning is changed without any complaint.
> I *do not* say this should be an int.
> This should be either implicicly a long (which would be capable of
> representing all results from int * uint) or at least some warning
> when compiling with -w.

I like both of those ideas :)

> But I must confess, after writing all the things above I tested around
> a bit again and saw: Implicit conversions other than the int * uint case,
> such as int * float do what I would expect.
> The int * uint thing got me so screwed in the past I casted everything
> manually because I feared D could do something evil ,-)
> 
> 
>> The root problem here is that you're trying to mix signed and unsigned operations together, and expecting a signed result.  My personal rule of thumb is: never, ever get signed/unsigned types within five kilometres of each other.  If you think something is signed, but aren't sure, assert it!
> 
> I sometimes have some problems with this, as said before: Let SDL return
> a width as uint and have your positions int (because they also can be negative).
> 
> I had this problems with C already. Examples of questions I have often when coding:
> - "Hmm okay. You're a on-screen coordinate. You will be positive.
>   But I might to want to mix you with virtual and potetially negative
>   Coordinates. Also you wont be larger than 32000, as long as screens
>   wont get really big. But I somehow feel I should make you an int..."
> - Hm okay so I have these few things I know of they wont be negative.
>   Should I make them int nevertheless? Would avoid complications and warinings,
>   and the value range wouldnt be a problem.
> 
>> I actually think a better solution would be to add an Integer type to D: one that actually, really, truly works like an integer, and not a member of Z_{2^32} :P
> 
> Yeah, like the python one. Should not be too hard to implement I guess.
> 
> Henning

Thanks to being able to overload opAssign, this should be possible to do in a fairly sane way now.  I wonder what the performance implications would be, though... I suppose it can't be any worse than Python's long type :P

The other idea I had ages ago was that it would be great if compilers actually gave us distinct native types for integers (which throw an exception if they over/underflow) and modulo integers (which wrap around quite happily).

	-- Daniel

-- 
Unlike Knuth, I have neither proven or tried the above; it may not even make sense.

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
« First   ‹ Prev
1 2 3 4 5 6