Self-esteem gone overboard: The perils of a global namespace


There are items with overly generic names. HANDLE, CloseHandle, GetObject, DIFFERENCE, query.exe. But their functionality doesn't live up to their name. HANDLE refers only to kernel handles, CloseHandle can only close kernel handles, GetObject only gets information about GDI objects, DIFFERENCE applies only to the numerical difference between group resources and standalone resources, and query.exe only queries information about Terminal Services Remote Desktop Services.

Why do functions that operate only inside a specific realm have names that suggest a broader scope?

Self-esteem gone bad.

You're on the kernel team. You have a handle manager. What should you call your handles? Well, since they're handles, just call them HANDLE. Because that's what they are, right? And naturally the function that closes HANDLEs should be called CloseHandle. Sure, there are other types of handles out there, but they don't exist in your world. Your world is the kernel, and in the kernel world, you can call them HANDLEs and everybody will know that you're talking about kernel handles because that's why you're in the kernel in the first place! Why would somebody pass a handle to a non-kernel object to a kernel function? That makes no sense!

Similarly, the GDI folks came up with their own object system, and naturally the way you get information about an object is to call GetObject. There's no confusion here, right? I mean, this is GDI, after all. What other types of objects are there?

The Terminal Services Remote Desktop Services folks thought the same thing when they created their query.exe program. Hey, this is a computer set up to run Remote Desktop Services; of course you want to query information about Remote Desktop Services.

Of course, when your symbol exists in a shared namespace, the context of your naming decision becomes lost, and your generic-sounding function name (which worked just great for generic operations in the world in which it was created) ends up carrying more meaning than you originally intended.

Commenter Sean W. tries to explains that Unix doesn't have this problem. "A Unix-flavored close() system call can close any file descriptor." This explanation ends up being its own counter-argument. When you say that it can close any file descriptor, you're admitting that it can't close anything. You can't use close() to close the objects opened by opendir() or dbm_open() or XtOpenDisplay.

"Well, yeah, but it can close any file descriptor regardless of where it came from." And CloseHandle works the same way: It can close any kernel handle regardless of where it came from.

Sean W. later clarified that "the scope of close() is the system kernel, so it's reasonable to expect that it applies to kernel data and no other data, whereas the scope of CloseHandle is all of Win32, including at least KERNEL/USER/GDI/ADVAPI." Um, actually, the scope of CloseHandle is also the kernel.

And in the category of "suggesting things that are already done" goes this comment from Daniel, who suggests that the documentation explain which HANDLEs can be closed by CloseHandle. Actually, if you look at each function that creates a handle, it also tells you the function to use to close it. Not quite the same thing, but since you have to open something in order to close it, you'll find the information even sooner.

Comments (45)
  1. Doug says:

    I agree completely.  I’m not sure that it is self-esteem rather than just complete blindness to the other programming contexts that will be using your interface, and the confusion that a poor namespace can create.   One should always review your public API design from the user’s point of view.

    However, this is just a manifestation of the experience issue.  IE, when you are having trouble just getting the simple everythingiscorrect case working, things like error cases and other boundary conditions are too hard to consider.

  2. John says:

    What’s wrong with using a common differentiator in your public interface?  I.e. KERNEL_HANDLE, Kernel_CloseHandle, GDI_OBJECT, GDI_SelectObject.   Yes, it’s ugly.  Yes, it’s a lot of extra typing.  However, the scope is clear.

    [You’re solving the wrong step (addressing the problem). The issue is that people are still stuck on the first step (realizing that there is a problem at all). -Raymond]
  3. Mark says:

    @John: There’s nothing wrong with that method, but that wasn’t Raymond’s point. His point was that these naming scope-creeps exist and an explanation of the likely mindset that led to their existence.

    The Terminal Services Remote Desktop Services

    folks thought the same thing when they created

    their query.exe program. Hey, this is a

    computer set up to run Remote Desktop

    Services; of course you want to query

    information about Remote Desktop Services.

    A related phenomenon is when developers of apps and utilities bundled with hardware assume that their hardware will be a user’s most valued possession:

    ‘Hey, this user’s just bought an Acme Scanner! Clearly he’ll want to be scanning all day long, let’s write a handy system tray utility to give him easy access to the scan function. It could even load on startup!’

  4. SRS says:

    Why not make the Windows source code browsable, so we can discover all this for ourselves? We know you have great influence – have quiet word with your legal dept., I can’t see them raising any objections.

    [The mental state of the developers is not recorded in the source code. -Raymond]
  5. Gabe says:

    This is like the email subject problem. When the GDI developer emails a question to the kernel developer, it never occurs to him that "question" or "kernel question" are bad subjects.

  6. Mark says:

    [The mental state of the developers is not recorded in the source code. -Raymond]

    Not in all cases… ;)

    http://www.kottke.org/06/10/google-code-search
    http://google.com/codesearch?hl=en&lr=&q=coding+drunk

  7. termserv says:

    The Terminal Services Remote Desktop

    Services folks thought the same thing when

    they created their query.exe program. Hey,

    this is a computer set up to run Remote

    Desktop Services; of course you want to

    query information about Remote Desktop

    Services.

    Of course, when query.exe was created, it was part of an OS that was only used for Terminal Services:

    http://www.microsoft.com/technet/archive/termsrv/default.mspx

  8. Marcus says:

    "Microsoft has even tried very hard in its promotional materials (and court cases) to convince people that such components are permanently inseparable."

    Factually incorrect.  That argument was specific to the HTML rendering components and has to do with with their removal rendering the OS distribution useless to the end user.

    If you want to see the capabilities and the limits of the modularity of Windows look at Embedded XP.

  9. Bryan says:

    Sean W.:

    You should probably clarify what you mean by "boot" when you refer to what Windows can and cannot do.  Windows is quite capable of booting with only the Kernel (the actual Kernel and not the "here’s what I’m redefining as the Kernel" Kernel) in place.

    "So one can make a pretty good argument that the Windows "kernel" conceptually and logically includes things like USER and GDI, regardless of whether they’re separate files on disk or not, regardless of whether their respective teams consider them distinct."

    By the same logic, I could make a pretty good argument that you’re a core component of the government of the country in which you live because you pay taxes, but I’m sure your government would disagree on many levels.  ( It’s a bad analogy but think government = Kernel, person = GDI/USER )

    I read your older posts just today and didn’t see anything taken out of context.  I’m also unsure from where you have gathered your information about what an "average developer" is.

  10. John says:

    Your argument doesn’t really make sense:

    A. This core operating system function returns a handle.

    B. CloseHandle, a core operating system function, closes handles.

    Therefore, CloseHandle should close all handles returned by core operating system functions (NT, KERNEL, USER, GDI, etc).

    The fundamental problem with that argument is that it’s not really accurate; a handle is not the same thing as a HANDLE.  In fact, if you replace HANDLE and CloseHandle with THINGY and CloseThingy, your entire argument ceases to exist.  So the real problem is that they chose a generic term to represent a specific object type.

  11. Ben Voigt [C++ MVP] says:

    <quote>how can a programmer be expected to realize that an HWND is a fundamentally different kind of handle than an HFILE or an HBITMAP</quote>

    You do realize that a file handle isn’t called an HFILE, right?  It’s a HANDLE.  All objects that can be passed to CloseHandle are just HANDLE, whether event, mutex, file, etc.

    There is no problem when STRICT is defined.  (Well, a user might still try the wrong thing first, but they will end up catching the error so early it isn’t really a big deal.)

    Appropriate RAII C++ wrapper classes make this really easy — there’s a totally consistent interface to closing all of them, the ‘delete’ operator.

  12. Caliban Darklock says:

    In short:  If all handles aren’t HANDLEs,

    then HANDLEs shouldn’t be called HANDLEs.

    This is only a problem on computers.

    The handle on a door cannot be used to pick it up, and the handle on a coffee mug cannot be used to open it.

    Which of them is "really" a handle?

    Assume it’s a door. The handles on some doors can only be pushed, not pulled. The handles on others can only be pulled, not pushed. Some door handles may be both pulled and pushed. Some doors do not have handles at all.

    Which of them is "really" a door handle?

    Is a doorknob a type of door handle?

    Clearly, this is a very complex and difficult question. And yet, somehow, everyone on the planet over the age of four knows how to open and close just about every door they ever encounter throughout their entire lives.

    Just because you can ask a question that is hard to answer does not mean that a large problem exists. Understanding that a handle is not necessarily a HANDLE is not a big deal to most Windows programmers, any more than it is a big deal to most *NIX programmers when they realise that not everything you can open is a file descriptor. It isn’t hard to grasp, and it isn’t hard to resolve. Suck it up, write the code, and get on with your work.

  13. Bryan says:

    CloseHandle specifically defines the exact types of objects it closes and even shows the exception ( and explains the possible behavior ) for closing a HANDLE returned by FindFirstFile:

    http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx

  14. nes says:

    Like clothes.launder() vs money.launder(), or shape.draw() vs blood.draw(), or matrix.norm() vs hi.norm() <wink>? I’m afraid English thrives on puns, and the same word routinely means radically different things across application areas. Therefore, to insist that a word have "one true meaning" in a programming language is insisting that the language cater to one true application domain. http://groups.google.com/group/comp.lang.python/msg/dbd738b6e1c67ef2

  15. nes says:

    Like clothes.launder() vs money.launder(), or shape.draw() vs blood.draw(), or matrix.norm() vs hi.norm() <wink>? I’m afraid English thrives on puns, and the same word routinely means radically different things across application areas. Therefore, to insist that a word have "one true meaning" in a programming language is insisting that the language cater to one true application domain. http://groups.google.com/group/comp.lang.python/msg/dbd738b6e1c67ef2

  16. sandman says:

    Sigh.

    I do a lot of *nix programming for fun. And quite a bit of Windows programming for profit. And quite frankly I think that SeanW – you a being a bit overdefensive.

    There a lots better places in the windows API for an unix vs windows attack. But I’m not going to look for them now.

    I have to say this particular API point has never worried me. Do as to what I think to ICANN idea of selling of parts of the top level of the global namespace is rather different.

    The selling and transfer of parts of this namespace is interesting as well – I’ve yet to see that cause a conflict in Java (or .NET) where the Icann namespace is used a an object namespace – but it probably only a matter of time .

  17. Jim says:

    One of my favorites is still convert.exe.  

    Of COURSE it’s for converting file systems; what else would you expect it to do?

  18. Peter says:

    There’s an interesting thing about unix "files" though: many groups have tried very hard to make sure that many things that are not at all alike are still "files".

    For example, Unix came up with the notion that your terminal is "just a file"; your keyboard is also "just a file".  When networking came in, the Berkeley people made sure that networks were also "just a file" (so that you can use the unix ‘select’ function on your keyboard (stdin), a file, and a network connection all at once).

    Modern versions of Linux have extended this with the ‘proc’ "filesystem": you can actually do an open on /proc/uptime and get uptime stats.  Similarly, /dev/mouse will give you the raw data your mouse is returning.

    This is a far cry from Windows, where each kind of object has its own set of functions to get them, use them, and dispose of them, and where each way to get information out of Windows is very different from each other.

    (The ‘inferno’ follow-on to unix takes the ‘everything is a file’ concept even further, and really does make everything a file).

  19. Peter says:

    There’s an interesting thing about unix "files" though: many groups have tried very hard to make sure that many things that are not at all alike are still "files".

    For example, Unix came up with the notion that your terminal is "just a file"; your keyboard is also "just a file".  When networking came in, the Berkeley people made sure that networks were also "just a file" (so that you can use the unix ‘select’ function on your keyboard (stdin), a file, and a network connection all at once).

    Modern versions of Linux have extended this with the ‘proc’ "filesystem": you can actually do an open on /proc/uptime and get uptime stats.  Similarly, /dev/mouse will give you the raw data your mouse is returning.

    This is a far cry from Windows, where each kind of object has its own set of functions to get them, use them, and dispose of them, and where each way to get information out of Windows is very different from each other.

    (The ‘inferno’ follow-on to unix takes the ‘everything is a file’ concept even further, and really does make everything a file).

  20. Karellen says:

    “Sure, there are other types of handles out there, but they don’t exist in your world. Your world is the kernel…”

    True.

    “Similarly, the GDI folks came up with their own object system[…]  What other types of objects are there?”

    Well, Kernel objects.

    In your world, there exists all the things in your world, *and all the things in the layers below you*.

    If you’re in the kernel, you’re lucky because there are no layers below you. You can name stuff whatever you want.

    If you’re in the lowest level userspace library (e.g. the C library) then you’re almost as lucky, and can name your stuff almost whatever you want, and reserve huge portions of namespaces for yourself. (e.g. str*(), mem*(), is*(), *_t, etc… – probably f*() as well)

    If you’re anyone else, you have to be aware of the lower level libraries – you couldn’t get much done if you didn’t. And given that you want a function to close/free something, but you’re aware that close(), fclose() and free() are already taken (because these are in the layers below you) you’re pretty much forced into confronting namespace issues.

    Hmmm….free() and close() are already taken. We’re the GDI project. How about GDIfree() to free our resources?

    As you point out, many other library teams have managed to work this sort of thing out for themselves, and carved out, for example, dbm_*() and Xt*() namespaces.

    [When GDI was written, the kernel didn’t have objects. Kernel objects didn’t arrive until almost years later. Oh, and GDI doesn’t use the C runtime library, so close() is not part of its world either. -Raymond]
  21. Sean W. says:

    Gee, there’s nothing quite like your having two-year-old quotes taken out of context in a public forum to wake you up in the morning.  Now I know how you must feel sometimes, Raymond ;-)

    > Um, actually, the scope of CloseHandle() is also the kernel.

    Sure, CloseHandle() is part of the *true* kernel, and is responsible for closing only *true* kernel handles, but really, that’s a pretty bad argument:  While a Un*x system can (and does!) exist as just a “small” kernel and one process with no shared libraries running under it, no such claims can be made of Windows:  NT and KERNEL and USER and GDI and the shell and a dozen other modules are all critical chunks of the system, and it won’t boot without all of them.  While they may not run in ring 0, they’re all a core part of the “operating system,” and the average programmer doesn’t consider them unrelated:  Microsoft has even tried very hard in its promotional materials (and court cases) to convince people that such components are permanently inseparable.  So one can make a pretty good argument that the Windows “kernel” conceptually and logically includes things like USER and GDI, regardless of whether they’re separate files on disk or not, regardless of whether their respective teams consider them distinct.

    So to 99% of the programmers out there, an HWND isn’t conceptually distinct from an HFILE or an HGDI:  They’re all handles and all come from the “kernel,” and therefore should all be closed by the “kernel” function named CloseHandle().  If Microsoft wanted USER and GDI and such to be considered logically distinct and separate modules, you’ve definitely been going about it the wrong way.

    Maybe you can blame that on the marketers, maybe on the lawyers, maybe on the documentation writers, but the upshot is that Windows has lots and lots of handles, and only about half of the ones the average programmer bumps into can be closed by CloseHandle(), which means it’s a crapshoot as to what you have to do to clean up a random HANDLE when you run into it.

    > Of course, when your symbol exists in a shared namespace, the context of your naming

    > decision becomes lost, and your generic-sounding function name (which worked just

    > great for generic operations in the world in which it was created) ends up carrying more

    > meaning than you originally intended.

    You can’t *possibly* be trying to claim here that the kernel team thought nobody else would ever see or use *any* of their APIs?  I’d like you to explain how the kernel team could think people would write applications that would run on their kernel without using any kernel names.

    [(1) The window manager is not part of what in Windows is called “KERNEL” (which is not the same as “all ring 0 code necessary to boot the operating system”). Perhaps when Windows 1.0 was designed back in 1983, the “low-level memory management and task scheduling services” should have been called something else (“CORE”? “BASE”?) but it’s too late to fix it now. (2) It probably never occurred to the kernel folks that anybody else would want to use the word HANDLE to refer to non-kernel objects. After all, the window manager doesn’t use HANDLEs, it uses HWNDs and HMENUs. GDI uses HFONTs and HBRUSHes. The name HANDLE was available for use, so they used it. -Raymond]
  22. Leif Strand says:

    I just looked at the prototype for close() on Unix:

    int close(int fd);

    Does this mean I can use it to dispose of integers when I am done with them?  Forgive me if this is a dunce question — I am but an average programmer.

  23. Timothy Fries says:

    > While they may not run in ring 0, they’re all a core part of the "operating system," and the average programmer doesn’t consider them unrelated

    Microsoft is responsible for the ignorance of the ‘average programmer’?  Certainly they go out of their way and make heroic efforts to try to accommodate programmers who don’t quite understand the internals, but if a programmer doesn’t understand the difference between the kernel, USER, and GDI — doesn’t understand that a HANDLE and an HWND and an HFILE and an HDC — things *that are named different* are different things; renaming a few functions isn’t really going to help them understand.

    Your explanation is a lot of hand-waving and irrelevant excuses for why, even though they’re pretty much the exact same thing, UNIX’s close() is just fine as a generic name in the global namespace, but Windows’ CloseHandle() is not.

  24. Sean W. says:

    > (1) The window manager is not part of what in Windows is called "KERNEL" (which is not the

    > same as "all ring 0 code necessary to boot the operating system"). Perhaps when Windows 1.0 was

    > designed back in 1983, the "low-level memory management and task scheduling services" should

    > have been called something else ("CORE"? "BASE"?) but it’s too late to fix it now.

    You completely missed my point.  The issue is that Windows is a large, monolithic design, and whether you call the thing "kernel" or "core" or "base" or whatever, it’s still just a big giant ball of indivisible code to most programmers.  KERNEL and USER may be separate components to the system designers, but they aren’t to the programmers.  You have functions like AddAtom() and Beep() and various Console() functions in KERNEL32.DLL, and those are pretty obviously user-interface functions; and then in USER32.DLL you have functions like ExitWindowsEx() that are conceptually "system" functions and should probably be part of KERNEL32.DLL, and FillRect() that should probably be part of GDI32.DLL, and GDI32.DLL has functions like MapWindowPoints() and ClientToScreen() that don’t belong there either.  The whole thing’s a blurry mess:  In GDI you have many window and system functions, in USER you have many system and graphics functions, and in KERNEL you have many graphics and UI functions.  Is it any wonder the average programmer can’t tell where one module ends and the other begins?  And when it all looks like one big ball of code, how can a programmer be expected to realize that an HWND is a fundamentally different kind of handle than an HFILE or an HBITMAP?  And even if he figures all that out, what will you tell him the first time he sees an HRESULT?

    It’s too late to fix all this now, of course, but it sure seems to me to smack of poor planning and poor communication between the original design teams.

    > After all, the window manager doesn’t use HANDLEs, it uses HWNDs and HMENUs. GDI uses

    > HFONTs and HBRUSHes.

    Seriously, you think *none* of them would consider that the "H" in "HWND" might stand for "handle"?

  25. Karellen says:

    "how can a programmer be expected to realize that an HWND is a fundamentally different kind of handle than an HFILE or an HBITMAP?"

    The same way they can realise that an fd is different from a FILE * from fopen(), which is closed with a different function than a FILE * from popen() which is different from a DIR *, which is different from a void * from malloc(), which is different from a void * from dlopen(), which is different from a void * from mmap(), which is different from a nl_catd, which is different from an iconv_t, etc… on another system.

    I think this is pretty basic programmer stuff, and quite distinct from the problem of not naming things well. On any system, you need to keep track what resources you own, where you got them from, and follow the appropriate procedure for each resource to release it properly. If the documentation for the place you got it from doesn’t tell you how to release it, you’re stuffed. If it does, but you don’t pay attention and use another function to try to release the resource, you’re still stuffed.

  26. Sean W. says:

    > So the real problem is that they chose a generic term to represent a specific object type.

    Quite right, they did:  But by choosing that generic name for a specific function, they promoted the notion that the specific function could handle generic data.  CloseHandle() says in its name that it *closes* *handles* — there’s no ifs, ands, buts, or caveats there.  So when presented with an HWND — a window handle — CloseHandle() proves itself to be a liar:  It doesn’t close handles; it closes *thingies*.  Had they named it CloseKernelHandle(), at least programmers *probably* wouldn’t be trying to feed it HRESULTs (don’t laugh; I’ve seen people do that) and anything else that has "handle" or "h" in its name somewhere.

    In short:  If all handles aren’t HANDLEs, then HANDLEs shouldn’t be called HANDLEs.

  27. Gabe says:

    In a sense, Unix has the inverse problem. Everything is called a "file descriptor", even though it can describe things that aren’t files (like processes, mice, and sockets).

  28. ozzmosis says:

    One of my favorites is still convert.exe.  

    Of COURSE it’s for converting file systems;

    what else would you expect it to do?

    Then there is the vaguely-named ‘convert’, supplied with the ImageMagick suite of utilities, often found on UNIX systems.  Typically it’s installed as /usr/bin/convert or /usr/local/bin/convert, so as to be in the default search path.  It converts between graphics file formats, in case you were wondering.

  29. Yuhong Bao says:

    "(The ‘inferno’ follow-on to unix takes the ‘everything is a file’ concept even further, and really does make everything a file)"

    And the Plan 9 that preceded Inferno as well.

  30. Mark Taylor says:

    One of the lovely things in Python’s design is the way every module (= file) has (is) its own namespace. In foo.py, you can write functions and classes with generic names like close() or List. You call them as close() and Connection(), while everyone else calls foo.close() and foo.Connection(). Cross-file name clashes are impossible unless you abuse import … as or have multiple modules with the same name.

    I would love to see this design used in more languages; it’s the simplest and cleanest solution for the problem of namespace creep that I’ve ever seen.

  31. Your Blog says:

    Your Blog is unreadable by those enforce the use of larger fonts.

    I use 16 Pt because I need to read my screen without strain. Sadly your CSS barfs and breaks over this constraint and your stupid menubar covers everything makes your blog unreadable.

    I’m probably not missing much.

  32. Mark says:

    Mark Taylor: this is called object oriented programming.  Look it up some time.  Windows is written in C, which was created before OO became popular.

  33. SRS says:

    @Mark: No, this is called namespacing, and that’s what this article is about. The ‘foo’ in the example is a module not a class.

  34. jcs says:

    Your Blog: I was able to increase my text size and read this page with no problems.

    Maybe it’s just you…

  35. Dean says:

    Your Blog: what browser are you using? Both Firefox and IE7 handle large fonts on this blog fine for me…

    "I’m probably not missing much."

    Then why are you even complaining?

  36. Mark says:

    SRS: fair enough, but namespacing is normally a feature of OO languages.  There’s nothing special about Python – C++, C#, VB and Java allow the same pattern.  OO is ultimately an exercise in reducing the global namespace¹.

    There’s little difference between nested classes and module-level namespacing, and if I had to lose a feature, it would be the latter.

    ¹ May be a lie.

  37. Marcus says:

    SQL has an excellent example of this type of myopic belly-button staring which creates a technology which actually works against its intended target of business data management. For a start there’s the keyword

    Programming languages are often pretty bad too. For instance, why is ‘new’ such a common keyword in languages, essentially stealing it from the real-world lexicon and dedicating it to the syntax of the underlying technology only?

    I’m drawing a blank right now, because I regularly find the need to throw up my arms at yet another basic real-world word stolen by some technology that’s in love with itself. I think it’s a major contributor to software complexity.

  38. Cheong says:

    KERNEL, USER, GDI and ADVAPI are 4 wraper library for the lower-level NTAPI libraries right? So it’s natural for me to use functions from the same library that creates it close it.

    Of course, that’s because I’m C# programmer who used to use them in wrapper library of difference namespace so I can tell. Perheps the IDE could also have the option to display which header file the function comes from in, say, Intellisense? (I seldom program in C/C++ now so I don’t know)

    [“KERNEL, USER, GDI and ADVAPI are 4 wraper library for the lower-level NTAPI libraries right?” Wrong in 1981 (NTAPI didn’t exist in 1981), and still wrong in 2008. -Raymond]
  39. Simon Buchan says:

    @Cheong: Yes, Visual Studio (at least 2008) shows you the header a definition came from in intellisense.

  40. Michiel says:

    It would be nice if Microsoft provided windows.hpp. That would be a C++ wrapper for windows.h, except that

    • HANDLE, HWND, etc would be types
    • Microsoft::Close() would be overloaded to close anything you pass in

    • Constants would be true, typed constants.

    Quite a bit of (correct) code would continue to compile with little more than a using namespace microsoft. But if well done, quite some incorrect code would stop compiling. Eg calling the wrong close function.

    Of course, UNIX should do the same. A file descriptor is not an int; fd/3 simply makes no sense. A file descript can be stored in an int.

  41. One of my favorites is still convert.exe.

    Of COURSE it’s for converting file systems;

    what else would you expect it to do?

    Proselytize at the user?  :)

  42. SuperKoko says:

    "A file descriptor is not an int; fd/3 simply makes no sense."

    fd/3 makes no sense, but fd+1 makes sense (e.g. as first parameter of select()).

    Using an absolute integer (0, 1, 2 and sometimes 3 or 4) as file descriptor makes sense too.

    In UNIX systems, file descriptor VALUES aren’t implementation details. They’re well documented. Knowing them is useful for parent-child communication.

    Whether this is good design is another matter.

    However, not all integers are file descriptors, which indicates the need of a typedef such as "typedef int fd_t;

    @Michiel: If you want a C++ binding to Windows API, use MFC.

    @SRS:

    Namespacing and OO are different issues, even though OO languages, through their class members, implement some form of namespacing.

    Modula-3 is a good example of non-OO language with namespaces.

  43. Florian says:

    One of the funny consequences of the global name space is that there are constants ERROR and NOERROR – and both are zero. (ERROR is used by some GDI functions, although many functions return 0 on failure, and NOERROR seems to be an alternative to S_OK)

    And there are API functions LoadImage and ImageLoad, and only the former does what one might expect: loading images from resources. ImageLoad is contained in a strange library that probably nobody has ever used.

  44. Yuhong Bao says:

    [“KERNEL, USER, GDI and ADVAPI are 4 wraper library for the lower-level NTAPI libraries right?” Wrong in 1981 (NTAPI didn’t exist in 1981), and still wrong in 2008. -Raymond]

    Only KERNEL32 and some of ADVAPI32 wraps ntdll.dll.

    [Only parts of KERNEL32 are wrappers. What this has to do with the original subject I’m not sure. -Raymond]
  45. My long-time favourite: main.cpl

    Try running it from "Start… Run", if you don’t know what it is!

Comments are closed.

Skip to main content