|
|
|
|
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Darren New <dne### [at] sanrrcom> wrote:
> On 7/24/2011 3:38, Orchid XP v8 wrote:
> > On 23/07/2011 06:37 PM, Darren New wrote:
> >
> >> Interesting.
> >
> > I'm ticked by "C++ crashes a lot if it's immature".
> >
> > What, if C++ is immature? Or the C++ codebase is immature? Or perhaps you
> > mean if the C++ developers are immature? ;-)
> I think they meant your code crashes a lot if it's written in C++ and hasn't
> had lots of debugging.
I think it depends a lot on the competence of the C++ programmer(s).
Granted, becoming a very competent C++ programmer (whose code seldom crashes,
or if it does, the crashes get caught very early on the development cycle)
may require more work than with some other languages, but it's not impossible.
Of course with C++ (and C and other C-compatible languages) the rare
circumstance where you get a nightmarish bug can be pretty fun. By
"nightmarish" I'm talking about the random crashes that happen sometimes
but not always (so that it's very difficult and laborious to get the program
to crash on purpose), where the debugger is of no help whatsoever even if
you are running in full debug mode (you either get no stack trace whatsoever,
or the stack trace is completely unhelpful because the crash happens
somewhere in the main runloop rather than in your code), where no debugging
tool is reporting any error (ie. no memory leaks, no zombie objects, no
misuse of STL, nothing), and the system does not have nor support tools like
valgrind. And you have no idea whatsoever which line from the tens of
thousands of lines of code is causing the problem (and that's if you are
lucky and it's just a bug in one line somewhere, rather than it being some
really hard to find combination of conflicts).
I wonder if something similar ever happens with the "safer" programming
languages (eg. you get a "null pointer exception" or some other similar
error and have absolutely no idea why, and no debugging tool is helping).
--
- Warp
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
>> I think they meant your code crashes a lot if it's written in C++ and hasn't
>> had lots of debugging.
>
> I think it depends a lot on the competence of the C++ programmer(s).
I imagine it also varies considerably depending on how complicated
whatever you're trying to implement is.
By the looks of it, these guys were trying to implement stuff like
routing, statistics, license management, encryption, distributed lookup,
and probably complex business rules as well, all in C++, while their
servers get hammered by customers of tier-1 game titles. I'd imagine
that kinda thing isn't fun.
> Granted, becoming a very competent C++ programmer
> may require more work than with some other languages, but it's not impossible.
I'd presume [although I could of course be wrong] that a company that
develops exclusively in C++ would go out of their way to hire only the best.
> Of course with C++ (and C and other C-compatible languages) the rare
> circumstance where you get a nightmarish bug can be pretty fun.
Yeah, gotta love bugs that move around depending on what compiler flags
you set or which version of some 3rd party library you link to. (E.g.,
anything involving broken pointer arithmetic usually ends up causing
random behaviour that varies depending on the exact compilation details.)
> I wonder if something similar ever happens with the "safer" programming
> languages (eg. you get a "null pointer exception" or some other similar
> error and have absolutely no idea why, and no debugging tool is helping).
In Java, accessing a null pointer would throw an exception, which (if
nothing else) will dump a stack trace to stderr.
In Haskell, accessing a null pointer would... be quite impressive,
actually. Given that the core language itself has no notion of "pointer"
nor what it means to be "null".
Probably the closest equivalent is the "head []" error. If some function
was expecting a list of data, but at runtime that list happens to be
empty, then the program prints "head []" to stderr and halts. [Unless
you wrote some exception handling code, of course.]
Good luck figuring out where in the entire program the problem actually
resides. What's that? Bracket the problem parts with print statements?
Ah, but perhaps you're forgetting; Haskell does not execute code in the
order written, and printing is only permitted from the IO monad.
Yes, there /is/ a debugger. No, it will /not/ give you a stack trace.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Invisible <voi### [at] devnull> wrote:
> > I wonder if something similar ever happens with the "safer" programming
> > languages (eg. you get a "null pointer exception" or some other similar
> > error and have absolutely no idea why, and no debugging tool is helping).
> In Java, accessing a null pointer would throw an exception, which (if
> nothing else) will dump a stack trace to stderr.
But if the null pointer is accessed in the depths of some obscure system
library which gets called by the main runloop of the program (rather than
being directly called by your code), you might end up in a situation where
the stack trace is completely unhelpful and you have no idea whatsoever
where that null pointer is coming from in your code (which might happen if
you are not using that precise system library directly, but it's a library
used by a library used by a library which you are using, but you don't know
what this chain might be, as the implementation of the library you are using
is hidden behind its public interface).
> In Haskell, accessing a null pointer would... be quite impressive,
> actually. Given that the core language itself has no notion of "pointer"
> nor what it means to be "null".
Well, I did say "or some other similar error".
> Probably the closest equivalent is the "head []" error. If some function
> was expecting a list of data, but at runtime that list happens to be
> empty, then the program prints "head []" to stderr and halts. [Unless
> you wrote some exception handling code, of course.]
> Good luck figuring out where in the entire program the problem actually
> resides. What's that? Bracket the problem parts with print statements?
> Ah, but perhaps you're forgetting; Haskell does not execute code in the
> order written, and printing is only permitted from the IO monad.
> Yes, there /is/ a debugger. No, it will /not/ give you a stack trace.
So how is that problem usually solved? "Just review the entirety of your
code and try to find the bug"?
--
- Warp
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
>> In Java, accessing a null pointer would throw an exception, which (if
>> nothing else) will dump a stack trace to stderr.
>
> But [...] you might end up in a situation where
> the stack trace is completely unhelpful and you have no idea whatsoever
> where that null pointer is coming from in your code.
Yes. I hate it when that happens. While accessing a pointer without
checking whether it's null is arguably a bug, knowing where this happens
often tells you nothing about how the heck the pointer came to *be* null
in the first place - and /that/ is usually the real bug.
I gather people use step debuggers and the like to hunt down such
things. Let's just hope the null pointer isn't because of some cruel
concurrent thread interaction. (There's a /reason/ why most people avoid
concurrency.)
>> In Haskell, accessing a null pointer would... be quite impressive,
>> actually. Given that the core language itself has no notion of "pointer"
>> nor what it means to be "null".
>
> Well, I did say "or some other similar error".
Sure. I was just pointing out that an entire class of very nasty bugs
completely fails to exist, and hence never needs to be debugged. Which
is a big win. However...
>> Probably the closest equivalent is the "head []" error.
...it's not the solution to everything.
>> Yes, there /is/ a debugger. No, it will /not/ give you a stack trace.
>
> So how is that problem usually solved? "Just review the entirety of your
> code and try to find the bug"?
It would be nice if that wasn't the actual answer, wouldn't it?
I should point out that the error message is actually telling you what
function threw an exception. In this case, the "head" function threw an
exception because it was given an empty list as input. So you only need
to look at places in your code that call "head".
Good coding practise dictates that if you call "head", you should check
the list isn't empty first, and throw your own more-specific exception
if the list /is/ empty somehow. (E.g., if a dictionary lookup uses a
list internally somehow, it should throw an exception like "lookup: key
not found" rather than just "head []".)
Still, this is one of the more frustrating things about Haskell. It's
somewhat offset by the fact that we have a REPL, and you really can run
most pure functions without having to initialise a whole bunch of stuff
in a certain order. (I.e., you /can/ easily test isolated functions.)
Even so...
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
On 7/25/2011 4:33, Warp wrote:
> Darren New<dne### [at] sanrrcom> wrote:
>> On 7/24/2011 3:38, Orchid XP v8 wrote:
>>> On 23/07/2011 06:37 PM, Darren New wrote:
>>>
>>>> Interesting.
>>>
>>> I'm ticked by "C++ crashes a lot if it's immature".
>>>
>>> What, if C++ is immature? Or the C++ codebase is immature? Or perhaps you
>>> mean if the C++ developers are immature? ;-)
>
>> I think they meant your code crashes a lot if it's written in C++ and hasn't
>> had lots of debugging.
>
> I think it depends a lot on the competence of the C++ programmer(s).
> Granted, becoming a very competent C++ programmer (whose code seldom crashes,
> or if it does, the crashes get caught very early on the development cycle)
> may require more work than with some other languages, but it's not impossible.
Well, I'd say it takes more time and more development. So if you count a
single program, or if you count all the programs over your career, the
comment is probably true. I.e., it also takes longer for a competent
programmer to get expert at C++ than it does for a competent programmer to
get expert at a simpler language.
> I wonder if something similar ever happens with the "safer" programming
> languages (eg. you get a "null pointer exception" or some other similar
> error and have absolutely no idea why, and no debugging tool is helping).
Occasionally. Usually it's something like running out of file handles, if
it's a low-level problem. I had that in Tcl once, and of course the thing
would have to run for hours before it ran out of handles, and I just
couldn't find where the problem was. The code was too complex in the error
handling, and I for whatever reason bashed my head on it for a couple of
days rather than refactor it, and I couldn't figure out which of the files
it was running out of (i.e., which of the several "open" calls wasn't
matching a "close").
The other kind of problem that's difficult is the large-scale logic problem.
I had something that could rebuild the cache from the data store (to
simplify the description). Then I added code to record changes to the data
store and apply them incrementally to the cache. And once every few days,
that would crash and fall back to rebuilding from scratch. And it took me a
while to figure out if someone added X and then deleted X all in one cycle,
when it tried to propagate "add X" to the cache, it was already gone from
the data store, so it gave up and fell back to the full rebuild. Fundamental
mistakes in architecture or algorithm don't get any easier with safer or
simpler languages.
The difference between the two is, you can reason from the program text. I
knew I was running out of file handles because somewhere in the code that
did open/read/write/close, one of the paths out of that code wasn't doing
the close. I had very high confidence that it wasn't some other third party
library stomping on my stack and changing the file handle variable to some
other value.
But, in all honesty, the number of "I can't find this nightmare bug" I've
encountered in safe languages is about the same as the number of "I found
the bug, and it's in the compiler/interpreter" kinds of nightmare bugs.
I can't tell you the number of times in unsafe languages where I spent three
days trying to figure out what was actually broken. To be fair, usually when
I'm using unsafe languages, it's often because the machine isn't powerful
enough or standard enough to support something like valgrind or even gdb, or
you're missing so much source that such tools aren't useful, so it's purely
reasoning from the code you actually have.
--
Darren New, San Diego CA, USA (PST)
"Coding without comments is like
driving without turn signals."
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
On 7/25/2011 6:42, Warp wrote:
> But if the null pointer is accessed in the depths of some obscure system
> library which gets called by the main runloop of the program (rather than
> being directly called by your code), you might end up in a situation where
> the stack trace is completely unhelpful and you have no idea whatsoever
> where that null pointer is coming from in your code (which might happen if
> you are not using that precise system library directly, but it's a library
> used by a library used by a library which you are using, but you don't know
> what this chain might be, as the implementation of the library you are using
> is hidden behind its public interface).
The stack trace in something like Java or Tcl is as useful as a full stack
trace from gdb is in C, when you haven't actually clobbered memory in the
unsafe languages. I.e., you walk up the stack until you find your code that
invokes the not-your-code, then you figure out what happened from there.
With the more OO stuff, the problem is figuring out which object you're
talking about, IME. An interactive debugger that lets you examine things at
the object-graph level solves that problem for the most part.
--
Darren New, San Diego CA, USA (PST)
"Coding without comments is like
driving without turn signals."
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Darren New <dne### [at] sanrrcom> wrote:
> The stack trace in something like Java or Tcl is as useful as a full stack
> trace from gdb is in C, when you haven't actually clobbered memory in the
> unsafe languages. I.e., you walk up the stack until you find your code that
> invokes the not-your-code, then you figure out what happened from there.
But that's the problem: The buggy part of your code might not be in the
call stack at all anymore at the time the null pointer exception (or whatever
other symptom) happens.
I know what a stack trace is and how to read it, and why I mentioned
several times that "the debugger is of no help whatsoever".
--
- Warp
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
On 7/25/2011 9:20, Warp wrote:
> But that's the problem: The buggy part of your code might not be in the
> call stack at all anymore at the time the null pointer exception (or whatever
> other symptom) happens.
Well, sure. I thought I had expressed it more clearly than that.
In the case that the broken code isn't the code in the call stack, you debug
it the same way you'd debug code in C or C++ that wasn't doing undefined
unsafe stuff - you'd figure out the infection that led to the error, figure
out the defect that led to the infection, and correct the defect.[*]
For example, if the null came from an instance variable, you'd find the
place the instance variable got initialized, breakpoint it, and see if it
gets set. If not, figure out why not. If so, figure out where it gets set
*again*, by breakpointing any assignment that sets it back to null. Etc.
The only difference in an unsafe language is you either need a debugger that
can breakpoint not based on source code (i.e., that you can breakpoint based
on writing to the memory via a wild pointer, which I imagine is most of them
these days at least on normal desktop-class machines). It's harder to
analyze because if you *can't* find the problem, you can't just say "find me
every reference to this variable in the codebase."
[*] Those are apparently the technical terms.
"Error: Program gave wrong results."
"Infection: Program state that is not as it should be."
"Defect: Code that made the program state other than what it should be."
--
Darren New, San Diego CA, USA (PST)
"Coding without comments is like
driving without turn signals."
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Warp <war### [at] tagpovrayorg> wrote:
> Of course with C++ (and C and other C-compatible languages) the rare
> circumstance where you get a nightmarish bug can be pretty fun.
It's even more fun when you painstakingly go through the entirety of
your code, commenting out one piece at a time, every time testing if the
crash still happens (a very tedious task because the crashes happen at
random and are not guaranteed to happen every time), until you are left
with basically nothing else than a completely bare-bones "main" function,
and the crash is still happening. At that point you realize that the problem
is not in your code after all but somewhere else, and you still have no idea
where, or how it should be fixed.
(On one hand it's a relief to know that I have not made an out-of-bounds
access or whatever, ie. my programming expertise really works. On the other
hand it sucks because the bug is still there, and now it's even more of a
mystery of why it happens and how it should be fixed.)
(And yes, talking from experience here.)
--
- Warp
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
On 7/27/2011 8:39, Warp wrote:
> It's even more fun when you painstakingly go through the entirety of
> your code,
I did that once when we were having these terrible crashes in a
large-for-the-time C program. Printed out an inch-thick stack of code and
read it line by line to make sure I hadn't screwed up some allocation.
(Found one bug that way, too, but it wasn't getting triggered by this case.)
But the problem wasn't in my code, but rather the supervisor's. He said
"What do we do about it?" I said "I tried to read your code, but I couldn't
even follow the top-level procedures, so you have to go thru it line by line
looking for the bug." He said "I don't have time to do that." I said "Then
you don't have time to fix the bug. I can't do it for you, because I don't
know what you expect your code to be doing."
Long story short, it turns out he'd been giving the wrong call-tree to the
overlay linker. So he not only didn't know what his bug was, he wasn't even
sure what order his code got called in.
--
Darren New, San Diego CA, USA (PST)
How come I never get only one kudo?
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
|
|