LWN.net Logo

Python slithers into Wesnoth

Python slithers into Wesnoth

Posted Jan 15, 2009 23:42 UTC (Thu) by tialaramex (subscriber, #21167)
In reply to: Python slithers into Wesnoth by njs
Parent article: Python slithers into Wesnoth

“the caller allocates it however it wants”

That's all very well if you don't care about abstractions or compatibility.

The advantage of the pointer is that when you change your rectangles from being two 16-bit co-ordinate pairs to one 32-bit co-ordinate pair and a 16-bit size pair, you know the rest of the code doesn't care about the difference between it was dealing with an abstract pointer, not a transparent structure with temptingly accessible named contents. And you know code compiled against the earlier version of the library won't now crash because the allocations are too small, because you're doing the allocations of the structure whose size changed in your library, which is also the only place accessing the structure contents.

Of course you don't /have/ to solve this with pointers. There's an equally valid tradition elsewhere of always having an array or a list, and returning only an opaque offset into the array or list. The calling code needn't care which convention you use.

"You never segfault" is one of those fun promises which assumes on the one hand, that if you'd done things some other way you'd have made mistakes (a correct program needn't take a segfault, at least not a fatal one) yet if you do things the supposedly superior way you won't make the equivalent mistakes. A fatal error is just as fatal if it's the runtime saying you accessed an uninitialised array member as if it's the OS saying you accessed an unmapped address.

-- And yes, maybe you could trap and ignore the array access error, but then your program will probably do something unpredictable and difficult to debug, just as it would if you signal(SIGSEGV, SIG_IGN);


(Log in to post comments)

Python slithers into Wesnoth

Posted Jan 16, 2009 0:02 UTC (Fri) by stijn (subscriber, #570) [Link]

A fatal error is just as fatal if it's the runtime saying you accessed an uninitialised array member as if it's the OS saying you accessed an unmapped address.

Yep. In my early days of C I was told: a segfault is what you get if you are lucky. Silent data corruption is worse.

Python slithers into Wesnoth

Posted Mar 15, 2009 16:14 UTC (Sun) by anomalizer (guest, #53112) [Link]

Anyone who has done serious C coding will agree with that.

Python slithers into Wesnoth

Posted Jan 16, 2009 4:44 UTC (Fri) by njs (subscriber, #40338) [Link]

>That's all very well if you don't care about abstractions or compatibility.

I had to stare at this for a while to figure out what you were saying...

I think you mean, "that's all very well if you aren't claiming to return a Foo but in fact returning a FooBar (a subclass of Foo chosen at runtime)"? That's a good point. In practice I find that the only times dynamic dispatch (virtual methods) pull their weight in C++ are when using the "strategy" pattern, and then it's usually the caller passing the subclass instance down and references work fine, but that's for my code in my projects; YMMV. I'm happy to add that to the list of exceptional cases where (smart) pointers are called for.

But in response to the rest of your comment, giving the calling code the ability to allocate the object does not mean that you have violated any abstractions. If my code says "give me a rectangle", and someone changes the size of a rectangle in the header file, then my code will allocate a differently sized object from then on. Binary (as opposed to source) compatibility is a little more work, but it just requires the usual pimpl technique that you usually need anyway if you want binary compatibility in a C++ library.

And of course there are always trade-offs, but that doesn't mean this is a zero-sum game. Pointer arithmetic/memory management is one of the most error-prone aspects of classic C/C++ programming (probably only threads are worse); eliminating it will, all else being equal, reduce your bug rate -- or at least, it worked for me.

It's also true that the other way you can segfault is by walking off the end of an array (well, arguably this is a special case of pointer arithmetic, but whatever). The answer to that is even easier: along with not using pointers, don't use arrays :-). Avoiding pointers in C++ takes some tricks, but avoiding arrays (and unchecked wrappers around them) is trivial and worthwhile. It won't stop you making indexing mistakes, but it can turn unreliable crashes/random memory corruptions into reliable clean exits that print the offending file and line number.

Copyright © 2012, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds