Bug in ruby?

David Vallner wrote:
In this case the bug was in the message not stating which variable had a
nil value. You may not think of it as serious, but he reports spending
several hours on it, and I'd call that a bug.

Frankly, in this case I would attribute that to the bug searcher and not the language. The message is pretty clear, it gives a line number and an easy explanation. With that, you can immediately spot where it goes wrong - even if you are unsure whether to look at the right or left side of the "+".

Remember, Ruby is being recommended to total neophytes as a good
language to start with. That means that good diagnostic error messages
are essential!

I have also previously requested that this get fixed in a future Ruby.
It's very annoying to try and guess which could be the offending
variable in a complex expression, and it wastes a lot of time. It
would surely be very easy for Ruby to say which variable was nil.

Actually I am not sure about this. The reason is this: the fact that the method does not exist in the receiver is not detected prior to runtime. And the object in question could potentially be referenced via any number of variables (including being part of an Array). As such the interpreter would have to remember several variable names per thread per object to actually be able to resolve this properly. Or it would have to go back to the source to determine this. And what do you do in this case where it is the result of a method call? As you see, it is not that easy and can incur some overhead you might not want to pay either.

Having said that, nobody forces you to create complex expressions. You can help readability and maintainability a lot if you break those down - which in turn makes debugging easier.

In some of my latest scripts I have this:

def preventNil(*args)
args.each_with_index do |arg, i|
   raise ArgumentError.new("argument #{i} cannot be nil") if arg.nil?
end
end

I'd be interested to hear if there are nicer solutions to this problem.

The problem I see here is that the fact it's not nil does not tell you that it is actually a proper value. So at best you only catch some errors with this approach.

Kind regards

  robert

···

On 21.11.2006 23:28, Leslie Viljoen wrote:

On 11/21/06, Charles D Hixson <charleshixsn@earthlink.net> wrote:

It just seems like it would be easier than that, since Ruby is an
interpreter. Doesn't the last sub-expression get stored in a string
somewhere as the expression is parsed?

Anyway, I am just now noticing that 5+nil and nil+5 return different
error messages. As long as an operator is unique in an expression, it
should be easy to figure out which is nil.

···

On 11/22/06, David Vallner <david@vallner.net> wrote:

Leslie Viljoen wrote:
> It's very annoying to try and guess which could be the offending
> variable in a complex expression, and it wastes a lot of time. It
> would surely be very easy for Ruby to say which variable was nil.

Meet my good friends, local variable, and return value checking. You'll
get along great once you get to know each other.

Also, see previous post. At any given point in time, there's several
variables that point to nil in the interpreter, and the culprit is also
usually an expression. Finding the possible expressions that returned a
nil would require tracing back to the literal in the stack frames, and
even then the last one wouldn't have to be the cause of the problem. I
stand by my point that this is not the job of a core language runtime,
but of manual or automated code review.

Hugh Sasse wrote:

Charles D Hixson wrote:

In this case the bug was in the message not stating which variable had a
nil value. You may not think of it as serious, but he reports spending
several hours on it, and I'd call that a bug.

This is one of the things I find irritating as well. Normally Ruby
is rightly praised for not getting in the way of productivity, but
this really does force one to program to meet constraints which are
not actually part of the language as such.

I'm not aware of a programming language that DOES report this. Remember

Some other languages report things differently....
        [...]

NullRefError in C#, or segfault in C would be. Since the undefined
method was #+, the culprit was the expression that a method of that name
was called on in that code snippet.

...but in many conventionally constructed arithmetic expressions there
will be more than one plus sign. Some languages use an arrow
        
        y = (a * x**3) + (b * x * x) + (c * x) + d
                       ^
                       >
-----------------------+

or similar. Evidence? The %p construct in vim errorformats
in compiler files for handling error messages, which uses
the arrow to pick up the column:

You might want to look up the definition of evidence, this is stretching
the word way, WAY too far.

I haven't been able to get either .NET/C# or Java to show me where on a
line a NRE/NRE occured.

The arrows you mention are probably for compile-time errors. Read: while
the source code is being read, is present in it's textual
representation, and the errors detected are ones that can be determined
from the structure of the source code. A NPE is a *runtime* error, long
after the textual form of the code is under green pastures.

So it looks like Ruby does this occasionally itself.
        [...]

Probably for parse-time errors.

It is completely irrelevant if some languages detect some classes of
errors with precise source code locations, or that Ruby does this sort
of diagnostics at parse-time for other classes of errors than the one at
hand, when you can't bring a specific, valid counterexample to my
statement, which is that I can't recall a language that does that for
runtime errors, specifically of the dangling pointer class of errors.

Provide me with an example where a runtime problem in a complex
expression like the one you mentioned gives you exact source code
position, preferrably in a programming language I've actually heard of
before (there's enough of those), and I'll concede this point.

Further diagnostics (why it could have possibly happened) is the role of
a static code analysis tool; since it's sooner or later guesswork it's

Which doesn't apply in dynamic languages like Ruby where method creation
on the fly is the norm (attr_accessor, method_missing, and more).

That's a price you pay for using a dynamic language with relatively
little mainstream penetration, those tools are harder to develop, have
to rely on less conclusive heuristics, there's a smaller market for them
and little chance of someone implementing them without a market because
they'd end up solving problems a lot of people consider a non-issue. If
you want tool support, Java beckons, otherwise wait until Ruby
equivalents emerge. It's also unrelated to the issue at hand.

Specifically, it doesn't imply (except in wishful thinking) that it
should be the job of the interpreter to provide possibly (probably)
unrelated "this -might- have gone wrong" type of information. The Ruby
interpreter's behaviour as it is is in my opinion correct and complete -
it provides the programmer with all the information it has at the time
from the information it needs to run the program. I am strongly opposed
to losing interpreter runtime efficiency (from keeping full program
source code intact in memory, for example) to provide heuristic diagnostics.

not the task of the interpreter itself.

Coding defensively and using sanity checks on the return value of #index
and other methods that may return nil would also have helped.

This doesn't mean that is is undesirable that Ruby do more. This is
shifting the burden from the developers of ruby to the many users
of it. Not to suggest that the developers have all the time in the
world, but to say that more people are affected by not having this than
are affected by having to implement it.

For me, it is undesirable. If it's a problem that can be solved within
the standard library by providing a set of DbC -ish metaprogramming
features, be it so. Same if it's a missing feature that can be
implemented without ambiguous output.

And for features that are clearly in the domain of code analysis tools,
I'm clearly against. Yes, such tools are absent in the Ruby domain. This
however doesn't imply the core interpreter should become one. I don't
want it to become a full-blown development tool, or any other form of
bloated monstrosity, the core responsibility of the interpreter is to
run Ruby code, and say when it can't stating the immediate reason why.

Now, I would be the first to say that writing parsers is not easy.
I have tried on a number of occasions, and frankly, I am rubbish at
it. Given the constraints imposed by YACC on the future of the
language (see other threads in the past) I suspect that moving to
some other parser may be helpful. But the point of this post is
that there is evidence from other languages that it is possible for
Ruby to be more helpful, there is a desire among its users that it
be more helpful.

I'll repeat that I haven't seen evidence that this class of errors is
diagnosed with the level of detail you'd like in a language with a
computation model similar to Ruby from you.

David Vallner

···

On Wed, 22 Nov 2006, David Vallner wrote:

Jim Cochrane wrote:

/ ...

The bug that cause Mars Polar Explorer to prematurely shut down its
engine and fall the last 100 meters to the surface of Mars, never to be
heard from again.

Due to a missing or incorrect unit conversion, right?!

No, I left that one off my list because it was simple human error, not
really software-related. One outfit was using English units, the other one
Metric, and they failed to realize the discrepancy until the spacecraft was
of course.

The error I am speaking of caused a Mars spacecraft to shut down its descent
engine prematurely due to the misreading of a sensor. At least that's the
best theory so far for a spacecraft that didn't have any terminal phase
telemetry.

Or how about the Ariane 5 (
http://www.around.com/ariane.html
).

Yep. Another bad one.

I don't remember ever hearing a description of the defect (or
defects) that caused the DIA baggage sysgtem to fail (
http://www.cis.gsu.edu/~mmoore/CIS3300/handouts/SciAmSept1994.html
).

I think that one was mostly bad mechanical design. They were trying to do
away with human baggage handlers entirely.

···

--
Paul Lutus
http://www.arachnoid.com

Charles D Hixson wrote:

/ ...

OTOH, it's also true that by compiling every time I enter a new
definition I can generally handle this error with minimal problems ....
but it would be a lot easier to include sufficient context markers to
ensure localization of errors.

Another solution makes use of a beautifier, frequently applied, that shows
how one is getting off track or misinterpreting the indentations. This is
how I sort things out as they get deep and complex.

I still prefer curly braces around everything, but that style is clearly
going out of fashion.

···

--
Paul Lutus
http://www.arachnoid.com

Hugh Sasse wrote:

/ ...

Coding defensively and using sanity checks on the return value of #index
and other methods that may return nil would also have helped.

This doesn't mean that is is undesirable that Ruby do more.

At the expense of runtime speed. Every added hand-holding feature in effect
at runtime decreases runtime speed.

This is shifting the burden from the developers of ruby
to the many users of it.

Your suggestion shifts the burden from developers of Ruby code to the end
users of Ruby programs, who would have to put up with time-costly error
detection features running in the background meant to detect and describe
runtime errors that ought to have been caught during the design phase.

IMHO this entire class of problem is better dealt with by better design and
better testing, not more loquacious error messages during runtime.

···

--
Paul Lutus
http://www.arachnoid.com

Leslie Viljoen wrote:

···

On 11/22/06, David Vallner <david@vallner.net> wrote:

Leslie Viljoen wrote:
> It's very annoying to try and guess which could be the offending
> variable in a complex expression, and it wastes a lot of time. It
> would surely be very easy for Ruby to say which variable was nil.

Meet my good friends, local variable, and return value checking. You'll
get along great once you get to know each other.

Also, see previous post. At any given point in time, there's several
variables that point to nil in the interpreter, and the culprit is also
usually an expression. Finding the possible expressions that returned a
nil would require tracing back to the literal in the stack frames, and
even then the last one wouldn't have to be the cause of the problem. I
stand by my point that this is not the job of a core language runtime,
but of manual or automated code review.

It just seems like it would be easier than that, since Ruby is an
interpreter. Doesn't the last sub-expression get stored in a string
somewhere as the expression is parsed?

Anyway, I am just now noticing that 5+nil and nil+5 return different
error messages. As long as an operator is unique in an expression, it
should be easy to figure out which is nil.

The thing is, Ruby is not returning "nil" error messages, it's returning error messages which are consistent across all NoMethodError and TypeError exceptions (in these cases). More generally, nil is not getting any kind of special treatment. I think this is kind of nice, personally.

-Justin

Leslie Viljoen wrote:

Also, see previous post. At any given point in time, there's several
variables that point to nil in the interpreter, and the culprit is also
usually an expression. Finding the possible expressions that returned a
nil would require tracing back to the literal in the stack frames, and
even then the last one wouldn't have to be the cause of the problem. I
stand by my point that this is not the job of a core language runtime,
but of manual or automated code review.

It just seems like it would be easier than that, since Ruby is an
interpreter. Doesn't the last sub-expression get stored in a string
somewhere as the expression is parsed?

Probably not, to my best knowledge, a source file is always tokenized
and parsed into an AST before interpreting. The interpreter would have
to do extra work to reconstruct the last expression, which might not
really be helpful always, or even in most cases. (Someone with more
information on the interpreter's internals could say this with more
authority.)

David Vallner

···

On 11/22/06, David Vallner <david@vallner.net> wrote:

Hugh Sasse wrote:
> or similar. Evidence? The %p construct in vim errorformats
> in compiler files for handling error messages, which uses
> the arrow to pick up the column:

You might want to look up the definition of evidence, this is stretching
the word way, WAY too far.

Are we talking evidence for civil or criminal cases here? :slight_smile:
I have provided evidence for diagnostic messages pointing to the point
in the line where the error occurs. I concede that usually this is
for syntax errors. See below.

I haven't been able to get either .NET/C# or Java to show me where on a
line a NRE/NRE occured.

The arrows you mention are probably for compile-time errors. Read: while

They generally are, I agree. I can't assert "always", and no, I
can't provide a counter example.

the source code is being read, is present in it's textual
representation, and the errors detected are ones that can be determined
from the structure of the source code. A NPE is a *runtime* error, long
after the textual form of the code is under green pastures.

There are reasons for not throwing that information away in an
interpreter.

>
> So it looks like Ruby does this occasionally itself.
> [...]
>

It is completely irrelevant if some languages detect some classes of
errors with precise source code locations, or that Ruby does this sort
of diagnostics at parse-time for other classes of errors than the one at
hand, when you can't bring a specific, valid counterexample to my

I don't tend to keep things with errors like this in lying around,
and can't remember off the top of my head.

statement, which is that I can't recall a language that does that for
runtime errors, specifically of the dangling pointer class of errors.

We are not discussing pointers. We are discussing method calls on
objects that don't support them, and stating where in the computation
this occurred.

Provide me with an example where a runtime problem in a complex
expression like the one you mentioned gives you exact source code
position, preferrably in a programming language I've actually heard of
before (there's enough of those), and I'll concede this point.

Just because nobody does it yet, it doesn't mean it can't be done.
        [...]

Specifically, it doesn't imply (except in wishful thinking) that it
should be the job of the interpreter to provide possibly (probably)
unrelated "this -might- have gone wrong" type of information. The Ruby

If it has the AST, it shouldn't have to be probabilistic. I'm
specifically not saying this is easy, I'm saying it is desirable,
and that I accept constraints.

        [...]

to losing interpreter runtime efficiency (from keeping full program
source code intact in memory, for example) to provide heuristic diagnostics.

For heuristic (guesswork), I'd agree. For sufficient exactitude, then
under control of an option (like -w) I'd be in favour.

>> not the task of the interpreter itself.
>>
>> Coding defensively and using sanity checks on the return value of #index
>> and other methods that may return nil would also have helped.
>
> This doesn't mean that is is undesirable that Ruby do more. This is
> shifting the burden from the developers of ruby to the many users
> of it. Not to suggest that the developers have all the time in the
> world, but to say that more people are affected by not having this than
> are affected by having to implement it.
>

For me, it is undesirable. If it's a problem that can be solved within
the standard library by providing a set of DbC -ish metaprogramming
features, be it so. Same if it's a missing feature that can be
implemented without ambiguous output.

I don't see how one could do that for something internal to the interpreter.

And for features that are clearly in the domain of code analysis tools,
I'm clearly against. Yes, such tools are absent in the Ruby domain. This
however doesn't imply the core interpreter should become one. I don't
want it to become a full-blown development tool, or any other form of
bloated monstrosity, the core responsibility of the interpreter is to
run Ruby code, and say when it can't stating the immediate reason why.

It's that 'statement of the reason why' I'd like improved.
Obviously there are trade-offs, and it is up to Matz. I'm simply
adding my voice to those that wish for improved diagnostics. If it
is impossible, or not practical at this time, or some other
sufficient constraint to prevent this, then fine. But if it is not
being done because there is no apparent desire for this, then I'd
like to say there is some desire for this. I fully accept that
this may run counter to other desirable attributes, such as speed
of execution, and a decision may not go in favour of better diagnostics
as a result. But to quote an early version of the Ruby Newsgroup FAQ:
http://www.rubycentral.com/faq/ruby_newsgroup_faq.txt
'You could characterize the Ruby philosophy as "there's a better way
to do it" (TABWTDI).'

        Hugh

···

On Thu, 23 Nov 2006, David Vallner wrote:

Leslie Viljoen wrote:

Leslie Viljoen wrote:
> It's very annoying to try and guess which could be the offending
> variable in a complex expression, and it wastes a lot of time. It
> would surely be very easy for Ruby to say which variable was nil.

Meet my good friends, local variable, and return value checking. You'll
get along great once you get to know each other.

Also, see previous post. At any given point in time, there's several
variables that point to nil in the interpreter, and the culprit is also
usually an expression. Finding the possible expressions that returned a
nil would require tracing back to the literal in the stack frames, and
even then the last one wouldn't have to be the cause of the problem. I
stand by my point that this is not the job of a core language runtime,
but of manual or automated code review.

It just seems like it would be easier than that, since Ruby is an
interpreter. Doesn't the last sub-expression get stored in a string
somewhere as the expression is parsed?

Remember in modern interpreted languages that interpretation and execution
are separate phases. The bug this thread is about was a runtime bug, not
one of interpretation. Once runtime begins in earnest, such niceties as
variable identities and even sometimes line numbers are lost in the name of
efficiency.

Anyway, I am just now noticing that 5+nil and nil+5 return different
error messages. As long as an operator is unique in an expression, it
should be easy to figure out which is nil.

In this case, some simple, focused testing strategies needed to be applied.
Notwithstanding the OP's insistence that he tried everything, there was an
obvious test he didn't apply.

···

On 11/22/06, David Vallner <david@vallner.net> wrote:

--
Paul Lutus
http://www.arachnoid.com

Jim Cochrane wrote:

/ ...

The bug that cause Mars Polar Explorer to prematurely shut down its
engine and fall the last 100 meters to the surface of Mars, never to be
heard from again.

Due to a missing or incorrect unit conversion, right?!

No, I left that one off my list because it was simple human error, not
really software-related. One outfit was using English units, the other one
Metric, and they failed to realize the discrepancy until the spacecraft was
of course.

The error I am speaking of caused a Mars spacecraft to shut down its descent
engine prematurely due to the misreading of a sensor. At least that's the
best theory so far for a spacecraft that didn't have any terminal phase
telemetry.

Thanks for the clarification. I had forgotten that there were two
different major Mars-mission errors.

Or how about the Ariane 5 (
http://www.around.com/ariane.html
).

Yep. Another bad one.

I don't remember ever hearing a description of the defect (or
defects) that caused the DIA baggage sysgtem to fail (
http://www.cis.gsu.edu/~mmoore/CIS3300/handouts/SciAmSept1994.html
).

I think that one was mostly bad mechanical design. They were trying to do
away with human baggage handlers entirely.

I did a bit of googling/reading on it when I posted the link. It sounded
like the main cause was bad management and planning - poorly managed
requirements creep, not allocating enough time for thorough analysis of a
complext system, etc. I think there were several system-design flaws,
some of which were mechanical, but I believe I read that software
defects also contributed to the problem. Just a general, overall
foobar-ification. (I've not heard how much, if any, of the original
DIA system is still in use these days; it'd be interesting to find out.)

···

On 2006-11-22, Paul Lutus <nospam@nosite.zzz> wrote:

--

Pardon my top posting, but I addressed these points in Ruby-Talk:226309.
        Hugh

···

On Sat, 25 Nov 2006, Paul Lutus wrote:

Hugh Sasse wrote:
>
> This doesn't mean that is is undesirable that Ruby do more.

At the expense of runtime speed. Every added hand-holding feature in effect
at runtime decreases runtime speed.

> This is shifting the burden from the developers of ruby
> to the many users of it.

Your suggestion shifts the burden from developers of Ruby code to the end
users of Ruby programs, who would have to put up with time-costly error
detection features running in the background meant to detect and describe
runtime errors that ought to have been caught during the design phase.

IMHO this entire class of problem is better dealt with by better design and
better testing, not more loquacious error messages during runtime.