| FullerData.com - News |
|
General News: BBC News Guardian News Telegraph News BBC UK BBC Technology BBC Business World Press Telegraph Opinion Scotsman Opinion Yahoo Opinion BBC In Depth BBC Magazine Techie News: Slashdot Kuro5hin Slashdot Developers Slashdot Games Slashdot Science PhysicsWeb Wired Technology PCWorld DevMaster GamaSutra Articles The Register TheServerSide .NET TheServerSide J2EE Sports News: Sport Headlines Football Motor Sport Cricket US Sport Microsoft: MSDN Architecture MSDN Patterns MSDN MSDN Magazine MSDN Web Services MSDN C# MSDN .Net Framework MSDN ASP.Net C# FAQ Database: MSDN SQL Server Oracle ASk Tom - Popular Oracle Ask Tom - Recent Oracle Blogs Other Techie: Code Project C# Stuff Live @ Sax.net Help .Net SQL Junkies DotNet Junkies 4GuysFromRolla.com Netcraft Blogs: Chris Brumme Martin Fowler Chris Sells Scott Watermasysk Sam Gentile Eric J. Smith Herb Sutter The Old New Thing Sam Ruby Tim Bray Tom Miller (MDX) Rico Mariani causticTech Johns Perf Blog |
TheOldNewThing: In an interview with the Seattle Times, Rod Hamlin of Opera Software claimed, We put a big red billboard out by Microsoft last year that said, "Want to be a real Internet explorer? www.opera.com." We got some interesting feedback on that. All of the AT&T executives could see it and all the Microsoft guys driving back home past Marymoor Park. Okay, so where was this billboard? He says it was near Marymoor Park, and that it could be seen from AT&T executive offices, which makes sense so far because AT&T Wireless has offices in the Redmond Town Center business and shopping center, which lies right across the highway from the park. But then things fall apart. First of all, there is no billboard stand anywhere along the stretch of highway that goes between Marymoor Park and Redmond Town Center. Second, if you go to the regulations governing highway advertising in the State of Washington [easier-to-read PDF version], section 47.42.040 describes the types of signs allowed, and the alleged Opera billboard does not appear to be any of permissible types. (The closest match would be 47.42.040(4), if Opera had offices within twelve miles of Redmond Town Center.) Third, you'd think there'd be plenty of pictures of an advertising campaign this cheeky. But I haven't been able to find any online. POIDH. Here's an actual cheeky prank (and the response). The Internet Explorer team since learned their lesson, and now they send congratulatory cake. Stop the presses: A colleague of mine says that he saw the sign. But it wasn't a billboard. Actually, it wasn't even a sign. It was a sponsorship banner hung on the fence of one of the sports fields at Marymoor Park, the sort of sign that more traditionally might read Bob's Auto Repair proudly supports youth sports. Go Mustangs!) I asked him why he didn't take a picture. "I guess we've all become pretty jaded. Either that or everybody figured somebody else would take a picture (so then nobody did)." After our conversation, he went and took a picture.
A customer had a question about named kernel objects:
When the last handle to a named kernel object
(such as a named semaphore or a named shared memory block)
is closed,
the object itself is destroyed.
Doesn't matter whether you explicitly closed the handle
by calling First of all, that would kind of belie the whole concept of clean-up. Cleaning up means destroying the resources the application neglected to. Second, this would create a bizarre situation where the way to access a new feature is to intentionally do something wrong. (Namely, to leak a handle to a named object.)
Okay, so maybe the expectation was that named objects persisted
after all handles to them are closed,
even if the handle is closed via the normal Kernel objects all follow the same lifetime rules, whether they are named or anonymous: The object is destroyed when the last reference to it is removed (when the handle is closed, noting also that running threads and processes keep a reference to the corresponding kernel object). If you want something that survives after all its handles are closed, then use something with a persistence model, like a file. Today's dubious security vulnerability is another example of If you reconfigure your computer to be insecure, don't be surprised that there's a security vulnerability. This example comes from by an actual security vulnerability report submitted to Microsoft:
I can just stop there because your brain has already stopped processing input because of all the alarm bells ringing after you read that first step. That first step gives away the farm. If you grant control to the entire contents of the Windows directory to non-administrators, then don't be surprised that they can run around and do bad things! "If I remove all the locks from my doors, then bad guys can steal my stuff." Yeah, so don't do that. This is not a security vulnerability in the door. Bonus chatter: There are many variations on this dubious security vulnerability. Actual vulnerability reports submitted to Microsoft include
That last one is impressive for its directness. "Starting on the other side of this airtight hatchway..." It wasn't long before people realized that the fish in the default wallpaper for the Windows 7 beta was a betta fish. This was intended to be a cute little pun, though some people took the semiotics to an extreme, Dude, this is Windows, not The Da Vinci Code. It's not like the people who chose the wallpaper are using a backchannel to pass secret messages to you like "I know I'm not supposed to tell you, but here's the Windows product schedule" or "Help, I'm trapped in a wallpaper factory!" They're just having a bit of fun. I have yet to see anybody point out that the fish was blowing seven bubbles. And no, I don't know what it "signifies". (I always wonder about the people who claim that the government embeds subtle messages about their complex conspiracies in plain sight. If you want to keep a secret, you don't run around talking about it!) A customer liaison asked the following question on behalf of his customer:
The value Reason Code: 0x84020004
The system shutdown reason codes
are documented in MSDN under the devious heading
System Shutdown Reason Codes.
In this case, the value SHTDN_REASON_FLAG_PLANNED 0x80000000 SHTDN_REASON_FLAG_CLEAN_UI 0x04000000 // reason.h SHTDN_REASON_MAJOR_OPERATINGSYSTEM 0x00020000 SHTDN_REASON_MINOR_RECONFIG 0x00000004
That value for In other words, this was a planned shutdown that was the result of an operating system reconfiguration. Perhaps somebody changed a system setting in the Control Panel, and in response to the question "The change you made requires that the system be restarted. Restart now?", the person said Yes. I was in the supermarket looking for cold medicine, and as is my wont, I like to read the fine print before choosing a product. Most of the products listed their active ingredients in the form Active Ingredient: XYZ 150mg. But there were a few that said Active Ingredient: XYZ 6X. What is this 6X? How much is 6X? Six times what? A closer look at the box reveals the word Homeopathic unobtrusively written towards the bottom of the box. The 6X notation means that the active ingredient's concentration is one part in 106, or one part in a million. Suppose the dosage is one teaspoon. That's about five milliliters, or about five grams of medicine. One millionth of that is 5 × 10-6 of a gram or 0.005 milligrams. By comparison, non-homeopathic medicines contain 13mg of the same medicine per dose. But that's okay, because practitioners of homeopathy believe that a medicine becomes more powerful the more heavily it is diluted. The Food and Drug Administration does not regulate homeopathic medicines very much at all because they contain little or no active ingredients. Do practitioners of homeopathy not wash their hands? After all, diluting the germs with water makes them stronger, right? The more you wash, the more powerful they become! Bonus homeopathy video: Homeopathic A&E as performed by British comedy show That Mitchell and Webb Look. (A&E = Accidents and Emergencies, what in the United States is commonly called the Emergency Room.) Bonus homeopathy satire: New Age terrorists develop homeopathic bomb.
In other parts of the world, religious images emerge from random patterns. Out here, we get Microsoft marketing. If I were on it, I could've charged admission. Andy Visser posted to the Suggestion Box something that wasn't so much a suggestion as a comment, presumably to get around the fact that comments on the original item had been closed: "I've found that the start bar seems to behave like it may be using this call incorrectly. I put my start bar on the left hand side of the screen. When I try to resize the bar (dragging its edge left and right), the system tray will dynamically move icons (based on tray width), seemingly disregarding the lock. The rest of the bar waits until MouseUp to redraw."
Actually, the taskbar (that's the name of the thing you're referring to)
does not call This comment demonstrates one of the common problems with bug reports submitted from the field: The description of the problem rarely includes the system configuration under which the problem occurs—they often don't even mention what operating system they're running! The person submitting the comment generally assumes that you will somehow know how their computer is configured (or believes that the problem is not configuration-dependent). This leaves people like me trying to reproduce the problem on various systems with various configurations before finally giving up and saying "Sorry, I don't see it." In some cases, the configuration setting that created the unwanted behavior is a setting whose sole purpose is to establish the unwanted behavior. For example, a customer reported, "Windows Vista is not displaying the user's picture on the Start menu or the logon screen. We discovered that the Apply the default user logon picture to all users policy prevents the user's customized picture from being displayed. We removed that policy, but that did not solve the problem. Is there anything else that might be causing this?" I found it interesting that the customer initially wondered why the user's custom picture wasn't showing up, when they had explicitly set the policy that says "Do not use the user's custom picture." But at least they figured that part out on their own. After some more questions, the customer explained that removing the policy restored the user's custom picture to the Start menu, but it nevertheless did not appear on the logon screen. (Thereby illustrating the problem of vague antecedents. When they wrote "that did not solve the problem", they weren't clear what the problem was. It turns out that they meant "that only solved part of the problem": The user picture appears on the Start menu, but not on the logon screen.) After additional rounds of troubleshooting, the customer eventually revealed that they had also set the policy Do not display last logged on user name. Um, if you disable showing the name of the last logged-on user, then the picture of the user doesn't appear either. (Maybe they took too literal a reading of the policy, expecting it to hide the name but not the picture? What would be the purpose of that? Exercise: Why isn't the policy called the more accurate Do not display information about last logged on user?)
If instead of calling No, but maybe yes. This is another one of the places where the C runtime behaves differently from raw Win32.
Under raw Win32, a process exits when any thread chooses to
exit the process explicitly
(usually by calling
On the other hand, the C runtime library automatically calls
This also means that if you decide to exit your main thread
by calling A customer had the following question: I'm using the You can't.
That window handle is used by the If you want to pass this information to the process being launched, you'll have to come up with your own mechanism for transferring this information. For example, you can pass it on the command line, or if you have a lot of information to pass, you can use a shared memory block. My young nieces live in a Chinese-speaking household, which is great for them because it means that when they grow up, they will be fluent in two languages. But it makes things a bit tricky at the beginning. The niece who is the subject of this story had just turned two at the time this story takes place, so her language skills even in Chinese are pretty rudimentary. Her language skills in English are restricted to a collection of set phrases like Excuse me!, I'm sorry!, What'you doing?, I want ice cream!, and any catch phrase from the character Dora the Explorer. (I'm also fairly sure she doesn't know what What'you doing? actually means. She'll come into a room and say, What'you doing? and then appear completely uninterested in the answer. I think she believes it to be a form of greeting and not an actual question.) She also loves to answer the phone, and this usually isn't a problem since most callers are relatives who can speak Chinese. But occasionally, it'll be somebody who speaks only English. (In general, these are just telemarketers, since most members of the household use their mobile phones as their main number.) Sometimes she'll run to the phone, pick it up, say "喂" (Hello), listen for a few seconds, and then just hang up. — Who was that on the phone? we'll ask. "人" is her one-word reply. It's hard to explain why this is a funny answer. The word 人 means man, person, so her response was a casual "A person." The offhand way she says it expresses her attitude that "The purpose of the telephone is to amuse me, but this was just some guy who provided no entertainment at all." The 人 phase lasted for only a month or so. In the next phase, she still picked up the phone and hung up when there was somebody speaking English on the other end, but when we asked her who it was, she gave a more detailed reply: "有人說ABC", which translates roughly as "It's some guy speaking A-B-C." ("A-B-C" being her word for the English language.) A customer noticed that when you right-click on Computer in the second column of the Start menu on Windows Vista, the first two options are Open and Explore. On the other hand, in Windows 7, the Explore option is gone, leaving just Open. The customer also noticed that in Windows Vista, the two commands had the same effect and wondered if Explore was removed because it was redundant. The response from the product team was a very simple "Yes." It's interesting when a customer notices a relatively insignificant UI change, figures out the likely reason for the change, and then asks for confirmation. It's not like the reason for the change affects anything. My guess is that the customer already paid for a support contract so they're just going to use it, even when the issue wouldn't normally be worth raising a support incident over. Today marks the 15th anniversary of the public release of Windows 95. During the development of Windows 95, one of the team members attended a Mac conference. And not as a secret agent, either. He proudly wore a Windows 95 team T-shirt as he strolled among the booths. The rest of us back at the mother ship wished him well and started discussing how we could get access to his dental records so we could identify his remains when they were sent back to us from the conference. When he returned, we didn't kill a calf in his honor, but we did marvel at his survival skills and asked him how it went. — I got a lot of funny looks. And one guy, upon confirming that I really did work on the Windows 95 project, said to me, "I have to commend you guys on Windows 95 so far. It sucks less." That backwards compliment tickled the team's funny bone, and it quickly became the unofficial team motto: Windows 95: It sucks less. Commenter Erbi has a program which creates a splash screen on a background thread while the main thread initializes. "I create and then destroy this splash screen window just before creating and displaying the main window." The problem is that the main window fails to obtain foreground activation. Commenting out the code that creates the splash screen fixes the problem, but then there isn't a splash screen any more (obviously). "Is there an explanation for this behavior?" This behavior is explained by two earlier blog posts, plus a PDC talk. The first blog post came out years before this question was asked: The correct order for disabling and enabling windows. Destroying a window is a rather extreme case of disabling it, but the effect is the same. When you destroy the splash screen, foreground activation needs to move to some other window, and since your main window isn't around to inherit it, foreground activation leaves your program. When the main window appears, it's too late. The PDC talk came next, followed shortly thereafter by a blog post version of the same talk. As marketing folks like to remind you, "You get only one chance to make a first impression." Similarly, you get only one chance to use your foreground activation permission, and you decided to blow it on a splash screen. That's fine as far as it goes, but if you want to transfer that permission to another window, you have to manage it yourself. The recommended way is to establish an owner/owned relationship between them; that's the case that the "disabling and enabling windows" article focuses on.
Miss Universe 2010 National Costumes, Part 1 Commentary in parts NSFW but they so deserve it. By definition, the primary monitor is the monitor that has (0,0) as its upper left corner. Why can't the primary monitor be positioned somewhere else? Well, sure you could do that, but then you'd have to invent a new name for the monitor whose upper left corner is at (0,0), and then you're back where you started. In other words, it's just a name. You could ask, "Why can't starboard be on the left-hand side of the boat?" Well, sure you could do that, but then you'd have to come up with a new name for the right-hand side of the boat, and then things are pretty much the same as they were, just with different names.
Perhaps a more descriptive (but clumsier) name for the primary monitor
would be the backward-compatibility monitor (for applications which
do not support multiple monitors),
because that's what the primary monitor is.
If an application is not multiple-monitor aware,
then any time it asks for properties of "the" monitor,
it gets information about the backward-compatibility monitor.
A call to
The window manager still respects window coordinates passed to
functions like
Multiple-monitor agnosticism is a term I just made up which refers
to programs which might not explicitly support multiple monitors,
but at least were open to the possibility of multiple monitors
by not making assumptions about the number of monitors but
instead using functions like It is not the case that the primary monitor is the applications show up here first monitor. As noted earlier, applications show up on whatever monitor they ask for, whether they asked for it explicitly (hunting around for a monitor and using it) or implicitly (restoring to the same coordinates they were on when they were last run).
Of course,
programs which pass The other day, I was in the office kitchenette, and two of my colleagues both named Paul happened to be there getting coffee. I quipped, "Oh no, is this legal? I think it's a violation of the Paul Exclusion Principle." It was a horrible physics pun, perhaps one of the worst I've made in a long time. My challenge to you is to come up with an even worse one that you've told. Note: You have to have actually made the pun to an appropriate audience. No fair just making one up for the purpose of the challenge. In Windows 7, the folder tree in the Explorer navigation pane by default no longer highlights the item in the view pane. This change was based on user testing and feedback, but if, like me, you prefer things the old way, you can play with two new check boxes on the Folder Options dialog. You can get to Folder Options in a variety of ways:
However you wind up there, the item you want to turn on is Automatically expand to current folder (or Expand to current folder if you use the super élite method). In the Customer Service and Support part of Microsoft, you will often see the term funnel. Here are some citations: Effectively and efficiently solve issues by driving levers across the entire funnel. Putting the Fun in Funnel. Strengthening the front of the funnel. The funnel is a way of viewing customer support engagements. For some reason, the funnel diagram is always drawn on its side with the mouth (the fat part) on the left and the stem (the narrow part) on the right. The width of the funnel represents the volume of customers at that stage of the support process, and the progress through the funnel represents how much time the customer has spent working on a solution. At the mouth of the funnel are the customers who turn to built-in product help, online help, forums, Knowledge Base articles, blog entries, training materials, and similar resources. A significant percentage of customers get the help they need via self-help, where the solution to their problem existed even before they asked the question; they just had to find it. The funnel narrows, and the customer picks up the phone or otherwise initiates a support incident. A support technician helps the customer via email, live chat, phone call, whatever. Another percentage of customers get their problem solved at this stage. It took longer, but the problem did get solved. At the stem of the funnel are the customers whose problems remain unresolved, and now things get bad. The problem takes days to resolve, multiple engineers get involved, and maybe even a site visit is called for. There is a concerted effort to improve the support resources at the front of the funnel. Of course, there are efforts to improve the support process at all of the stages, but the front of the funnel is a particular area of focus, since that's where everybody starts out, and that's where most users get their solutions. The term front of the funnel is in such heavy use it even gets its own acronym: FoF. Is it pronounced foff? Beats me. The first time you open a WinHelp file, you get this pen-writing-in-book animation while WinHelp does um something which it passes off as preparing Help file for first use or something similarly vague. I remember a conversation about that animation. The Windows shell team suggested to the author of WinHelp that the program use the shell common animation control to display that animation. After all, it's a short animation and it met the requirements for the animation common control. But the author of WinHelp rejected the notion. (Pre-emptive "I can't believe I had to write this": This conversation has been exaggerated for effect.) "Your animation control is so huge and bloated. I can do it much smaller and faster myself. The RLE animation format generates frames by re-rendering the pixels that have changed, which means that at each frame of the animation, a new pen image would be recorded in the AVI file. The pen cycles through three different orientations at each location, there are ten locations on each row, and there are four rows. If I used an RLE animation, that'd be 3 × 10 × 4 = 120 copies of the pen bitmap. Instead, I have just three pen bitmaps, and I manually draw them at the appropriate location for each frame. Something like this:
// NOTE: For simplicity, I'm ignoring the "turn the page" animation
void DrawFrame(int frame)
{
// Calculate our position in the animation
int penframe = frame % 3; // 3 pen images per location
int column = (frame / 3) % 10; // 10 columns per row
int row = (frame / 30) % 4; // 4 rows
int i;
POINT pt;
DrawBlankPage(0, 0); // start with a blank sheet of paper
// Draw the "text" that the pen "wrote" in earlier rows
for (i = 0; i < row; i++) {
DrawTextScribble(i, 0, 9);
}
// Draw the partially-completed row that the pen is on now
DrawTextScribble(row, 0, column);
// Position the pen image so the pen tip hits the "draw" point
GetTextScribblePoint(column, row, &pt);
DrawPenBitmap(penBitmaps[penframe], pt.x - 1, pt.y - 5);
}
"See? In just a few lines of code, I have a complete animation. All I needed was the three pen images and a background bitmap showing a book opened to a blank page. This is way more efficient both in terms of memory and execution time than your stupid animation common control. You shell guys could learn a thing or two about programming." "Okay, fine, don't need to get all defensive about it. We were just making a suggestion, that's all." Time passes, and Windows 95 is sent off for translation into the however many languages it is localized for. A message comes in from some of the localization teams. It seems that some locales need to change the animation. For example, the Arabic version of Windows needs the pen to write on the left-hand pages, the pen motion should be right to left, and the pages need to flip from left to right. Perhaps the Japanese translators are okay with the pen motion, but they want the pages to flip from left to right. The localization team contacted the WinHelp author. "We're trying to change the animation, but we can't find the AVI file in the resources. Can you advise us on how we should localize the animation?" Unfortunately, the WinHelp author had to tell the localization team that the direction of pen motion, and the locations of the ink marks are hard-coded into the program. Since the product had already passed code lockdown, there was nothing that could be done. WinHelp shipped with a pen that moved in the wrong direction in some locales. Moral of the story: There's more to software development than programming for performance. Today we learned about localizability. Commenter winhelp (probably not his/her real name) wonders what happened to WinHelp.exe. I don't know, but it turns out the answer was already known to the Internet. At the time the question was posted, the answer was already in the Wikipedia entry for Windows Help—it even had a citation! The question does highlight another one of those no matter what you do, somebody will call you an idiot dilemmas. On the one side, we have "Windows is already so big, what's the harm in adding another megabyte to the size to add this feature that is rarely used, primarly by older applications, so that customers won't have to download it?" On the other side, we have "Windows is too big, why not get rid of the components that exist only for the benefit of older applications and make them optional downloads?" What probably swung the pendulum to the remove it from the core product side is the fact that the Windows help file format is equivalent to an EXE. (I don't know this personally; I'm just reading the Wikipedia article.) If somebody can trick you into clicking on a rogue HLP file, they can run arbitrary code and take over your account. The underlying functionality is useful, because you can write help files with links like Click here to open the Options dialog, and clicking the link will actually open the Options dialog (by invoking some accompanying native code that calls whatever APIs are necessary to get that Options dialog to open). WinHelp came from the days before the Internet, when HyperCard was the reigning champion for page-based information presentation. You didn't have to worry that double-clicking a file on a remote server might take over your computer because you couldn't contact remote servers in the first place! (And if you could, it was because you were on a local-area network where all the computers were operated by your co-workers or other people you trusted.) As I recall, there are some help-file-based viruses out there, so the security aspect is not merely a theoretical discussion. Removing the attack surface from the default configuration reduces the value of the help file attack. (Historians may note that HyperCard also permitted execution of arbitrary native code attached to a HyperCard deck. There were also HyperCard viruses.) But now that you mention WinHelp, I remember a story about the little pen-writing-in-book animation that appears when the help engine is "preparing Help file for first use" (whatever that means). I'll take that up tomorrow.
Finalization is the crazy wildcard in garbage collection.
It operates "behind the GC",
running after the GC has declared an object dead.
Think about it: Finalizers run on objects that have no active references.
How can Finalizers are a Ouija board, permitting dead objects to operate "from beyond the grave" and affect live objects. As a result, when finalizers are involved, there is a lot of creepy spooky juju going on, and you need to tread very carefully, or your soul will become cursed. Let's step back and look at a different problem first. Consider this class which doesn't do anything interesting but works well enough for demonstration purposes:
class Sample1 {
private StreamReader sr;
public Sample1(string file) : sr(new StreamReader(file)) { }
public void Close() { sr.Close(); }
public string NextLine() { return sr.ReadLine(); }
}
What happens if one thread calls Having this race condition is clearly an unwanted state of affairs since the result is unpredictable.
Now let's change the
class Sample2 {
private StreamReader sr;
public Sample2(string file) : sr(new StreamReader(file)) { }
~Sample2() { sr.Close(); }
public string NextLine() { return sr.ReadLine(); }
}
Remember that we learned that an object becomes eligible for garbage collection when there are no active references to it, and that it can happen even while a method on the object is still active. Consider this function:
string FirstLine(string fileName) {
Sample2 s = new Sample2(fileName);
return s.NextLine();
}
We learned that the
Boom, we just hit the race condition we considered when
we looked at Classically speaking, there are three conditions which in combination lead to this problem:
The first condition (containment) is something you do without a second's thought. If you look at any class, there's a very high chance that it has, among its fields, a reference to another object.
The second condition (incomplete encapsulation)
is also a common pattern.
In particular, if
The third condition (propagation of destructive effect) is the tricky one.
If an operation on entity Unless the destructive method is a finalizer. If the destructive method is a finalizer, then you do not have complete control over when it will run. And it is one of the fundamental laws of the universe that events will occur at the worst possible time.
Enter
(Here's the money sentence.)
You need to use
The problem is that it's not always clear which objects have
finalizers which have destructive effect on a contained object.
There are some cases where you can suspect this is happening
due to the nature of the object itself.
For example, if the object manages something external to the CLR,
then its finalizer will probably destroy the external object.
But there can be other cases where the need for
A much cleaner solution than using This is one of the reasons I don't like finalizers. Since they operate underneath the GC, they undermine many principles of garbage collected systems. (See also resurrection.) As we saw earlier, a correctly-written program cannot rely on side effects of a finalizer, so in theory all finalizers could be nop'd out without affecting correctness. The garbage collector purist in me also doesn't like finalizers because they prevent the running time of a garbage collector to be proportional to the amount of live data, like say in a classic two-space collector. (There is also a small constant associated with the amount of dead data, which means that the overall complexity is proportional to the amount of total data.)
If I ruled the world, I would decree that the only thing you can do in
a finalizer is perform some tests to ensure that all the associated
external resources have already been explicitly released, and if not, raise
a fatal exception:
Bonus reading More than one customer has asked a question like this: I'm looking for a way to search for all instances of a particular type at runtime. My goal is to invoke a particular method on each of those instances. Note that I did not create these object myself or have any other access to them. Is this possible? Imagine what the world would be like if it were possible.
For starters, just imagine the fun you could have if you could
call
More generally, it breaks the semantics of AppDomain
boundaries,
since grabbing all instances of a type lets you get objects from
another AppDomain,
which fundamentally violates the point of AppDomains.
(Okay, you could repair this by saying that the
This imaginary On top of that, you break the syncRoot pattern.
class Sample {
private object syncRoot = new object();
public void Method() {
lock(syncRoot) { ... };
}
}
If it were possible to get all objects of a particular class,
then anybody could just reach in and grab your private syncRoot
and call Monitor.Enter() on it.
Congratuations, the private synchronization object you created
is now a public one that anybody can screw with,
defeating the whole purpose of having a private syncRoot.
You can no longer reason about your syncRoot because you are no longer
in full control of it.
(Yes, this can already be done with reflection, but at least when
reflecting, you know that you're grabbing somebody's private field
called syncRoot, so you already recognize that you're
doing something dubious.
Whereas with
GetInstances,
you don't know what each of the returned objects is being used for.
Heck, you don't even know if it's being used!
It might just be garbage lying around waiting to be collected.)
More generally, code is often written on the expectation that an object that you never give out a reference to is not accessible to others. Consider the following code fragment:
using (StreamWriter sr = new StreamWriter(fileName)) {
sr.WriteLine("Hello");
}
If it were possible to get all objects of a particular class,
you may find that your customers report that they are getting an
Nope, what happened is that some other thread did exactly what the
customer was asking for a way to do:
It grabbed all existing More generally, consider the graffiti you could inject into all output files by doing
foreach (StreamWriter sr in typeof(StreamWriter).GetInstances()) {
sr.Write("Kilroy was here!");
}
or even crazier
foreach (StringBuilder rb in typeof(StringBuilder).GetInstances()) {
sb.Insert(0, "DROP TABLE users; --");
}
Now no If you could obtain all instances of a type, the fundamental logic behind computer programming breaks down. It effectively becomes impossible to reason about code because anything could happen to your objects at any time.
If you need to be able to get all instances of a class,
you need to add that functionality to the class itself.
( (And I haven't even touched on thread safety.) Bonus reading: Questionable value of SyncRoot on Collections. A customer asked the rather enigmatic question (with no context):
The CLR does not maintain reference counts, so there is no reference count to "get". The garbage collector only cares about whether an object has zero references or at least one reference. It doesn't care if there is one, two, twelve, or five hundred—from the point of view of the garbage collector, one is as good as five hundred. The customer replied,
As already noted, the GC does not implement the "count the number of references to this object" algorithm. It only implements the "Is it definitely safe to reclaim the memory for his object?" algorithm. A null garbage collector always answers "No." A tracing collector looks for references, but it only cares whether it found one, not how many it found.
The discussion of "variables pointing to the same objects" is
somewhat confused, because you can have references to an object
from things other than variables.
Parameters to a method contain references,
the implicit It's clear that this person solved half of his problem, and just needs help with the other half, the half that doesn't make any sense. (I like how he immediately weakened his request from "I want the exact reference count" to "I want to know if it is greater than one." Because as we all know, the best way to solve a problem is to reduce it to an even harder problem.) Another person used some psychic powers to figure out what the real problem is: If I am reading properly into what you mean, you may want to check out the
The customer explained that he tried
The customer still hasn't let go of the concept of reference
counting, since he says that the object is "released".
In a garbage-collected system, object are not released;
rather, you simply stop referencing them.
And disposing of an object still maintains a reference;
disposing just invokes the
FileStream fs = new FileStream(fileName);
using (fs) {
...
}
At the end of this code fragment, the
using (FileStream fs = new FileStream(fileName)) {
...
}
the variable
The fact that the It does mean that between the splurges, the garbage collector does not know whether an object has outstanding references or not. It doesn't find out until it does a collection. The null garbage collector takes this approach to an extreme by simply hoarding pennies and never spending them. It saves a lot of money but consumes a lot of memory. The other extreme (common in unmanaged environments) is to spend the pennies as soon as possible. It spends a lot of money but reduces memory usage to the absolute minimum. The designers of a garbage collector work to find the right balance between these two extremes, saving money overall while still keeping memory usage at a reasonable level.
The customer appears to have misinterpreted what the
The name
The behavior the customer is seeing is correct.
The odds that the garbage collector has run between annihilating
the last live reference and checking the Note also that forcing a generation-zero collection does not guarantee that the object in question will be collected: It may have been promoted into a higher generation. (Generational garbage collection takes advantage of typical real-world object lifetime profiles by spending only fifty cents on a partial collection rather than a whole dollar on a full collection. As a rough guide, the cost of a collection is proportional to the number of live object scanned, so the most efficient collections are those which find mostly dead objects.) Forcing an early generation-zero collection messes up the careful balance between cheap-but-partial collections and expensive-and-thorough collections, causing objects to get promoted into higher generations before they really deserve it. Okay, that was a long discussion of a short email thread. Maybe tomorrow I'll do a better job of keeping things short.
Bonus chatter:
In addition to the Bonus reading: Maoni's WebLog goes into lots of detail on the internals of the CLR garbage collector. Doug Stewart created this handy index. Many people responded to Everybody thinks about garbage collection the wrong way by proposing variations on auto-disposal based on scope:
What these people fail to recognize is that they are dealing with object references, not objects. (I'm restricting the discussion to reference types, naturally.) In C++, you can put an object in a local variable. In the CLR, you can only put an object reference in a local variable. For those who think in terms of C++, imagine if it were impossible to declare instances of C++ classes as local variables on the stack. Instead, you had to declare a local variable that was a pointer to your C++ class, and put the object in the pointer.
This world where you can only use pointers to refer to objects is the world of the CLR. In the CLR, objects never go out of scope because objects don't have scope.¹ Object references have scope. Objects are alive from the point of construction to the point that the last reference goes out of scope or is otherwise destroyed. If objects were auto-disposed when references went out of scope, you'd have all sorts of problems. I will use C++ notation instead of CLR notation to emphasize that we are working with references, not objects. (I can't use actual C++ references since you cannot change the referent of a C++ reference, something that is permitted by the CLR.)
Oops, we just double-disposed the Let's say there's some attribute you can put on a local variable or parameter to say that you don't want it auto-disposed on scope exit.
Okay, that looks good. We disposed the
Let's do some trivial code cleanup, like inlining the
Whoa, we just introduced a semantic change by what seemed like a harmless
transformation:
The
Wait, we're not done yet.
What does
Oops, there is still a reference to that
Working backward, this means that we should have put a
The C++ solution to this problem is to use something like
I was sort of assuming that since you're here for CLR Week, you're one of those people who actively chose to use the CLR and want to use it in the manner in which it was intended, rather than somebody who wants it to work like C++. If you want C++, you know where to find it. Footnote ¹ Or at least don't have scope in the sense we're discussing here.
² As for an attribute for specific classes to have
auto-dispose behavior,
that works only if all references to auto-dispose objects are
in the context of a create/dispose pattern.
References to auto-dispose objects outside of the create/dispose pattern
would need
to be tagged with the
[AutoDispose] class Stream { ... };
Stream MyClass.GetSaveStream()
{
[NoAutoDispose] Stream stm;
if (saveToFile) {
stm = ...;
} else {
stm = ...;
}
return stm;
}
void MyClass Save()
{
// NB! do not combine into one line
Stream stm = GetSaveStream();
SaveToStream(stm);
}
|