Broken tools
Posted by aogWednesday, 21 November 2007 at 17:30 TrackBack Ping URL

Gah! Consider the following program:

# include "stdafx.h"
# include <memory>

struct A
{
    A() : _member(0) {}
    void method() { _member += 1; }
    int _member;
};

int _tmain(int argc, _TCHAR* argv[])
{
    std::auto_ptr<A> pA;
    pA = new A; // THIS SHOULD NOT COMPILE!
    pA->method();
}

This will compile and crash in Visual Studio 2005. The documentation doesn’t even have a warning that assignment of a raw pointer to an auto_ptr is a bad idea. If you want to talk about a language feature that is totally useless, auto_ptr has to be at the top of the list. What the !%#$^&*@ were the C++ designers thinking when they came up with this? Although, I will admit, according to the standard this shouldn’t even compile — it took the Dark Empire to make a useless thing actively dangerous.

Comments — Formatting by Textile
Gideon Thursday, 22 November 2007 at 23:05

This is one reason I avoid the use of ‘smart’ pointer templates. They add at least as much complexity (and gotchas) as they purport to remove*. I’m always re-reviewing the template definition to recall the quirks and gotchas of a particular implementation.

*Rule #22 in the book “Effective COM: 50 Ways to Improve your COM and MTS-based Applications”, by Don Box.

Gronker Friday, 23 November 2007 at 12:23

Msoft has pretty much converted to C# internally. If you want a strongly typed, completely safe C environment, give C# a shot. Ive never liked Msoft’s C++ implementation much, but I have to say, for what it is, C# is friggin’ easy to use and nearly idiot-proof.

Gideon Friday, 23 November 2007 at 14:32

It depends on which part of the Beast. Some MS teams appear to embrace C# while others seem to ignore or even shun it. The latter includes the teams that do Windows Core, Windows Server, Networking, Security, Installer, DirectX, and Aero/DWM.

The new Vista GUI can only be accessed from C/C++ (or P/Invoke’d), such as Aero Glass, the task dialogs, the new object explorer, and the new common file dialogs. One concludes that the Vista GUI team doesn’t seem to like C#. Then there’s the team that wrote Windows Sidebar, which supports only .NET and has no C/C++ API at all. Go figure.

The bottom line is that C/C++ programming on Windows is still an essential skill in many areas.

Gronker Friday, 23 November 2007 at 17:43

True enough, but for managed code (applications) C# is the mandate. I know a few guys internal that dont like it, but thats not going to do any good. I dont see C# working for driver development, though it would do fine compiled to a non-managed target, mostly because of the huge base of existing code in C++.

I am shocked about Vista and C#. I would would love to have been a fly on the wall in some of those meetings. .NET framework and C# go hand in hand. If they break that ease of use with Vista, they are in trouble indeed.

Annoying Old Guy Friday, 23 November 2007 at 19:50

Gideon;

No way. I have to a large extent stopped worrying about memory management since I started using smart pointers, which more than compensates for any small additional complexity in using them. In fact, I don’t ever use raw pointers anymore unless some third party API specifically requires it. I don’t see how you can build reliable, non-leaking code without them, except by hand rolling even more baroque mechanisms. If you have to review the implementation, you’re using poor ones and should upgrade to Boost.

Gronker;

I have looked at C# a bit. The lack of reliable deallocation makes much of my standard programming style infeasible. It’s a big part of the reason that I could never “get” Java. I tried the latter for 4 months or so but it was just too — “mitteny” is the best I can describe it, because it felt like wearing mittens while trying to code in it. No multiple inheritance, no ability to implement methods in an interface — just too restrictive, too indeterminate. Not that C++ doesn’t have some serious design flaws, but I can work around them better than C#’s and Java’s. If I want that kind of management, I’ll use Perl or Javascript, which are both nice little languages. I regret, now, disrespecting LISP in my early days, before I understood enough to truly appreciate it. Ah, for acces to the power of something like CLOS today!

Gronker Saturday, 24 November 2007 at 02:27

Hehe, I just was sitting here wishing I had a PDP-11 to keep my feet warm… ahh, the old days.

Im not a C# pundit, by any stretch. I still miss assembler and cross-compiling. I have avoided C++ over the years because I have always contended that OOP was just a way to make mediocre programmers able to work with each other with out blowing things up. But, I have slowly begun to fall in love with OOP as a few projects that screamed for it.

All that said, after reading the Wrox C# book on why MS made some of the decisions they made and the rational behind them… Im slowly coming over the the darkside of C#. I can do just about everything I ever could in C (and C++) with the ease of the .NET framework where everything in the Windows presented as objects. Even for my “real programming” thats an awefully nice way to do the mundane UI stuff.

Im not sold on the JIT compilation stuff or managed code in general, like you said I would rather malloc() and free(). But when you see why MS forced such strong typing in C# so that the garbage collector actually works correctly (unlike Java) I have to tip my hat.

But then, I miss:

mode   rewrite
at     10,10
write  I miss Orange Dots
cjm Saturday, 24 November 2007 at 09:45

did somone say pdp-11 ? western digital had a sweet little box that used a pdp-11 cpu with alternate microprogramming that implenented the ucsd pascal p-codes. it’s native language was in effect pascal. the entire o/s was written in pascal. just a fun environment.

Annoying Old Guy Saturday, 24 November 2007 at 10:51

People have done OOP since modularity was discovered, they just didn’t call it that. It’s just a slightly more rigorous form is all. The people who annoy me are the ones who say “C++ yuck!” then implement C++ structure by hand. E.g., have a struct “Bob” then write functions “Bob_construct”, “Bob_delete”, etc. so you have all of the overhead of C++, plus the joy of maintaining it by hand, along with the possiblity of making a typo and violating your own invariants. That’s why I haven’t called malloc / free for years. There isn’t much you can do with those that you can’t do as well and safer with std::vector.

Annoying Old Guy Saturday, 24 November 2007 at 10:53

PDP-11? I have got to use one of those myself. But I did like the LSI-11, quite an excellent machine. The only one I’ve seen better was the Motorola-88000.

Gideon Saturday, 24 November 2007 at 13:36

Container classes, RAII, etc, are all wonderful and useful ways to hide the management of allocation/deallocation of resources. No argument there. The problem is trying to write a general-purpose ‘smart’ pointer template that can handle a pointer to anything. Such a pointer template can never handle all scenarios of likely use. Either it uses refcounting (and screws up cycles), or it uses RAII (and screws up aliases outside the context), or some other scheme where something else will go wrong.

You have to read the template definition to learn the implementation to know which kinds of usage are legal. In my opinion (and Don Box’s) it is better to avoid such ‘general’ constructs, which lull you into thinking you can do things you can’t, and instead write your own constructors/destructors or your own IDispose/finalizers that correctly fit your particular usage scenario.

Gronker Saturday, 24 November 2007 at 14:45

Was it a PDP-11 or LSI-11 that we had under the table that used to warm my feet at Entropy, AOG? ‘Course, you were AYG back then.

Gideon: I agree, but I still dont like that I dont control when the garbage collector comes around or what order the collection is run in. Its more that Im used to being in control of that sort of thing, but the idea of objects just stitting on the curb, waiting for the garbage truck is not comforting to me.

Annoying Old Guy Sunday, 25 November 2007 at 18:56

Gronker;

We had a PDP-8, but I don’t think we ever turned that on. If we had one that was functional, it must have been an LSI-11.

Gideon;

I have to strongly disagree with you and Box. To me, that’s saying “one shouldn’t use std::list because it doesn’t handle all situations”. No, but it handles 98% of them so overall you’re ahead of the game to use it when it’s useful and hand roll the exceptions, rather than hand roll all the time. Smart pointers are also something easy to get wrong, so it’s not clear to me that you’re even minimizing the bug count by avoiding them even if you use them incorrectly sometimes. For the Boost smart pointers, it’s even easier because the RAII style won’t compile if used incorrectly.

I also don’t understand what you mean by “write your own destructors”. Well, yeah — when can you avoid that? How is that different from “write your own classes”? The smart pointers delete and the class destructor handles any special casing that’s needed to handle your particular usage scenario.

Gronker Sunday, 25 November 2007 at 19:21

We had it on one winter, the winter that we ended up burning the furniture for heat when the heater blower was running backwards. I just remember it being VERY loud and alot of cussing trying to get a terminal hooked up to it. I want to say it belonged to ‘Roid but it might have been a Regency leftover. Dont really remember…

Gideon7 Monday, 26 November 2007 at 03:15

There may be some confusion between a general purpose pointer-to-anything (like auto_ptr) and a container class. There is no argument that container templates are useful — lists, vectors, arrays, stacks, B-trees, maps, treaps, etc, are all wonderful ways to encapsulate resources. They are characterized by a well-defined public interface that is congruent to the data structure being represented. Access to the encapsulated data is limited to the interface.

The problem with the pointer-to-anything is that the interface contract is too vague. It makes promises it cannot deliver. Seemingly benign operations like assignment can trash the application unless you know exactly how the so-called ‘general’ smart pointer works.

Annoying Old Guy Monday, 26 November 2007 at 08:27

Then you’re using badly designed and written smart pointers. For the ones I use, the contract is very specific (“target will be deleted when the reference count goes to zero”) and you have to really work at it to get a crash. Anything that appears benign but is dangerous doesn’t compile. For instance, you can assign from a ptr<T> to a ptr<U> if and only if T is a subclass of U. Assignment the other way requires an explicit cast, or it doesn’t compile.

I’m sorry to prattle on, but I am absolutely astonished, as in nearly a decade of using generic smart pointer templates I have yet to encounter the problems you describe, even when writing very complex and memory intensive applications, such as an OODB on top of SQL, and using smart pointer templates for all memory access.

Interestingly, there was a bunch of experimentation with so called “policy pointers”, where one could specify what was done when the target object was to be disposed of, but that was abandoned because it was too complex and fragile.

Post a comment