<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5213006533208608117</id><updated>2011-11-28T04:53:58.902+04:00</updated><category term='C++'/><category term='Games'/><category term='Dummy'/><category term='Platforms'/><category term='Performance'/><category term='Windows'/><category term='PE'/><category term='WPF'/><category term='Mac OS'/><category term='C'/><category term='XAML'/><category term='.Net'/><title type='text'>Down the Rabbit Hole</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://wonder-mice.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://wonder-mice.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>wonder.mice</name><uri>http://www.blogger.com/profile/04581796828247171007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5213006533208608117.post-5103442884587116535</id><published>2010-03-04T01:18:00.001+03:00</published><updated>2010-03-04T18:00:49.598+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac OS'/><title type='text'>AuthorizationExecuteWithPrivileges() will fail with errAuthorizationInternal if there is no TEMPDIR</title><content type='html'>On Mac OS X function AuthorizationExecuteWithPrivileges() will fail with error errAuthorizationInternal (-60008, "something else went wrong.") if environment variable TMPDIR points on invalid (not existent) path. The reason of such weired behavior is call to tmpfile() inside the AuthorizationExecuteWithPrivileges() function. The moral is - use more explanatory error codes :)&lt;br /&gt;&lt;br /&gt;Some more info on that issue can be found in &lt;a href=http://lists.apple.com/archives/apple-cdsa/2007/Sep/msg00015.html&gt;Apple Mailing Lists&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5213006533208608117-5103442884587116535?l=wonder-mice.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wonder-mice.blogspot.com/feeds/5103442884587116535/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wonder-mice.blogspot.com/2010/03/authorizationexecutewithprivileges-will.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/5103442884587116535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/5103442884587116535'/><link rel='alternate' type='text/html' href='http://wonder-mice.blogspot.com/2010/03/authorizationexecutewithprivileges-will.html' title='AuthorizationExecuteWithPrivileges() will fail with errAuthorizationInternal if there is no TEMPDIR'/><author><name>wonder.mice</name><uri>http://www.blogger.com/profile/04581796828247171007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5213006533208608117.post-8850236203781687873</id><published>2010-02-14T00:36:00.001+03:00</published><updated>2010-02-14T00:39:00.467+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><category scheme='http://www.blogger.com/atom/ns#' term='XAML'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net'/><title type='text'>Classes generated from XAML (in WPF) are public by default</title><content type='html'>In Windows Presentation Foundation, classes generated from XAML markup have &lt;i&gt;public&lt;/i&gt; visibility by default. Why not &lt;i&gt;internal&lt;/i&gt; (like interfaces)? I don't want my application GUI private classes to be visible from the outside of its assembly. More over, it is not possible to alter that default in language-neutral way. One need to use &lt;i&gt;x:ClassModifier&lt;/i&gt; attribute in XAML root element to change class visibility specifying language-dependent value (&lt;i&gt;internal&lt;/i&gt; for C#, &lt;i&gt;Friend&lt;/i&gt; for VB). &lt;br /&gt;&lt;br /&gt;Links on the topic:&lt;br /&gt;- &lt;a href=http://weblogs.asp.net/okloeten/archive/2007/11/20/5292593.aspx&gt;Nice post about that problem&lt;/a&gt;&lt;br /&gt;- &lt;a href=http://msdn.microsoft.com/en-us/library/ms754029.aspx&gt;MSDN article on &lt;i&gt;x:ClassModifier&lt;/i&gt;&lt;/a&gt;&lt;br /&gt;- &lt;a href=http://connect.microsoft.com/VisualStudio/feedback/details/460114/wpf-x-classmodifier-is-not-language-neutral&gt;Microsoft Connect ticket on that problem&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5213006533208608117-8850236203781687873?l=wonder-mice.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wonder-mice.blogspot.com/feeds/8850236203781687873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wonder-mice.blogspot.com/2010/02/classes-generated-from-xaml-in-wpf-are.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/8850236203781687873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/8850236203781687873'/><link rel='alternate' type='text/html' href='http://wonder-mice.blogspot.com/2010/02/classes-generated-from-xaml-in-wpf-are.html' title='Classes generated from XAML (in WPF) are public by default'/><author><name>wonder.mice</name><uri>http://www.blogger.com/profile/04581796828247171007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5213006533208608117.post-5144558303117153202</id><published>2009-11-25T00:09:00.003+03:00</published><updated>2011-07-05T14:03:13.027+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><title type='text'>The right way to check whether the C string is empty</title><content type='html'>It is:&lt;br /&gt;&lt;pre class="code-cpp"&gt;char *s;&lt;br /&gt;// .. do something with s ...&lt;br /&gt;if (!*s) printf("empty!\n");&lt;/pre&gt;or&lt;br /&gt;&lt;pre class="code-cpp"&gt;if (0 == *s) printf("empty!\n");&lt;/pre&gt;I prefer the second one, because find it easier to read, but it doesn't matter really.&lt;br /&gt;&lt;br /&gt;The most popular &lt;b&gt;bad&lt;/b&gt; ways to do this:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;pre class="code-cpp"&gt;if (0 == strlen(s)) printf("empty\n");&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;pre class="code-cpp"&gt;if (0 == strcmp(s, "")) printf("OMG, empty!\n");&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;And it is not a joke, today I saw 2 independent reviews with such kind of stuff.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;p.s. There is a popular joke about how foreign developers check bool value to be a true: &lt;pre class="code-cpp"&gt;if (4 == strlen(bool2str(value))) printf("its true!\n");&lt;/pre&gt;&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5213006533208608117-5144558303117153202?l=wonder-mice.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wonder-mice.blogspot.com/feeds/5144558303117153202/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wonder-mice.blogspot.com/2009/11/right-way-to-check-whether-c-string-is.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/5144558303117153202'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/5144558303117153202'/><link rel='alternate' type='text/html' href='http://wonder-mice.blogspot.com/2009/11/right-way-to-check-whether-c-string-is.html' title='The right way to check whether the C string is empty'/><author><name>wonder.mice</name><uri>http://www.blogger.com/profile/04581796828247171007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5213006533208608117.post-3835300096159027277</id><published>2009-11-08T11:49:00.149+03:00</published><updated>2009-11-08T13:36:42.302+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Structure and class methods have external linkage</title><content type='html'>Lets look on small example:&lt;br /&gt;&lt;b&gt;File f01.cpp:&lt;/b&gt;&lt;br /&gt;&lt;pre class='code-cpp'&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;struct TEST&lt;br /&gt;{&lt;br /&gt;    TEST() { printf("TEST from f01: created\n"); }&lt;br /&gt;    unsigned m;&lt;br /&gt;};&lt;br /&gt;void f01()&lt;br /&gt;{&lt;br /&gt;    TEST t;&lt;br /&gt;    printf("TEST from f01: sz=%u\n", (unsigned)sizeof(t));&lt;br /&gt;}&lt;/pre&gt;&lt;b&gt;File f02.cpp:&lt;/b&gt;&lt;br /&gt;&lt;pre class='code-cpp'&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;struct TEST&lt;br /&gt;{&lt;br /&gt;    TEST() { printf("TEST from f02: created\n"); }&lt;br /&gt;    unsigned m1;&lt;br /&gt;    unsigned m2;&lt;br /&gt;};&lt;br /&gt;void f02()&lt;br /&gt;{&lt;br /&gt;    TEST t;&lt;br /&gt;    printf("TEST from f02: sz=%u\n", (unsigned)sizeof(t));&lt;br /&gt;}&lt;/pre&gt;&lt;b&gt;File main.cpp:&lt;/b&gt;&lt;br /&gt;&lt;pre class='code-cpp'&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;void f01(); // prototype&lt;br /&gt;void f02(); // prototype&lt;br /&gt;int main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;    (void)argc; (void)argv;&lt;br /&gt;    f01();&lt;br /&gt;    f02();&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;Program output:&lt;/b&gt;&lt;br /&gt;&lt;pre class='output-console'&gt;TEST from f01: created&lt;br /&gt;TEST from f01: sz=4&lt;br /&gt;TEST from f01: created&lt;br /&gt;TEST from f02: sz=8&lt;/pre&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;As you can see structure &lt;i&gt;TEST&lt;/i&gt; from &lt;i&gt;f01.cpp&lt;/i&gt; will be constructed in both &lt;i&gt;f01()&lt;/i&gt; and &lt;i&gt;f02()&lt;/i&gt; functions. In function &lt;i&gt;f02()&lt;/i&gt; it will be allocated 8 bytes for &lt;i&gt;TEST&lt;/i&gt; structure (since it has two unsigned members in &lt;i&gt;f02.cpp&lt;/i&gt;), nevertheless constructor of &lt;i&gt;TEST&lt;/i&gt; from &lt;i&gt;f01.cpp&lt;/i&gt; will be called. I think it is clear enough that calling incorrect constructor is a bad thing, and it is better to avoid it.&lt;br /&gt;&lt;br /&gt;The reason of such behavior, is that structure and class methods have external linkage. It is done to make it possible to use structure or class from another translation unit (*.cpp file). Therefor compiler will generate two &lt;i&gt;TEST::TEST()&lt;/i&gt; external symbols, one for each &lt;i&gt;TEST&lt;/i&gt; structure. Linker, when linking all three files together, will not be able to understand what &lt;i&gt;TEST::TEST()&lt;/i&gt; to use in every particular case, so it will pick just the first one. I don't know why there is no linkage warning (or even error) for such situation (in both gcc and MSVC).&lt;br /&gt;&lt;br /&gt;The solution is to put declaration of &lt;i&gt;TEST&lt;/i&gt; structure in anonymous namespace:&lt;br /&gt;&lt;b&gt;File f01.cpp:&lt;/b&gt;&lt;br /&gt;&lt;pre class='code-cpp'&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;namespace {&lt;br /&gt;    struct TEST&lt;br /&gt;    {&lt;br /&gt;        TEST() { printf("TEST from f01: created\n"); }&lt;br /&gt;        unsigned m;&lt;br /&gt;    };&lt;br /&gt;}&lt;br /&gt;void f01()&lt;br /&gt;{&lt;br /&gt;    TEST t;&lt;br /&gt;    printf("TEST from f01: sz=%u\n", (unsigned)sizeof(t));&lt;br /&gt;}&lt;/pre&gt;&lt;b&gt;File f02.cpp:&lt;/b&gt;&lt;br /&gt;&lt;pre class='code-cpp'&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;namespace {&lt;br /&gt;    struct TEST&lt;br /&gt;    {&lt;br /&gt;        TEST() { printf("TEST from f02: created\n"); }&lt;br /&gt;        unsigned m1;&lt;br /&gt;        unsigned m2;&lt;br /&gt;    };&lt;br /&gt;}&lt;br /&gt;void f02()&lt;br /&gt;{&lt;br /&gt;    TEST t;&lt;br /&gt;    printf("TEST from f02: sz=%u\n", (unsigned)sizeof(t));&lt;br /&gt;}&lt;/pre&gt;&lt;b&gt;Program output:&lt;/b&gt;&lt;br /&gt;&lt;pre class='output-console'&gt;TEST from f01: created&lt;br /&gt;TEST from f01: sz=4&lt;br /&gt;TEST from f02: created&lt;br /&gt;TEST from f02: sz=8&lt;/pre&gt;By putting declarations in anonymous namespace we force them to have internal linkage, and therefor not to confuse linker with their symbols.&lt;br /&gt;&lt;br /&gt;Bonus example:&lt;br /&gt;&lt;b&gt;File f01.cpp:&lt;/b&gt;&lt;br /&gt;&lt;pre class='code-cpp'&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;struct TEST { unsigned m; };&lt;br /&gt;void f01() { TEST t; }&lt;/pre&gt;&lt;b&gt;File f02.cpp:&lt;/b&gt;&lt;br /&gt;&lt;pre class='code-cpp'&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;struct TEST { std::string s; };&lt;br /&gt;void f02()&lt;br /&gt;{&lt;br /&gt;    TEST t;&lt;br /&gt;    printf("t.s=\"%s\"\n", t.s.c_str());&lt;br /&gt;}&lt;/pre&gt;Example will crash since constructor of &lt;i&gt;TEST&lt;/i&gt; structure from &lt;i&gt;f01.cpp&lt;/i&gt; doesn't call constructor of &lt;i&gt;TEST::s&lt;/i&gt; member from &lt;i&gt;f02.cpp&lt;/i&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5213006533208608117-3835300096159027277?l=wonder-mice.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wonder-mice.blogspot.com/feeds/3835300096159027277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wonder-mice.blogspot.com/2009/11/structure-and-class-members-have.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/3835300096159027277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/3835300096159027277'/><link rel='alternate' type='text/html' href='http://wonder-mice.blogspot.com/2009/11/structure-and-class-members-have.html' title='Structure and class methods have external linkage'/><author><name>wonder.mice</name><uri>http://www.blogger.com/profile/04581796828247171007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5213006533208608117.post-2527321117118849524</id><published>2009-11-07T22:38:00.001+03:00</published><updated>2009-11-07T22:50:30.764+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><title type='text'>Top level window receives WM_GETMINMAXINFO before WM_NCCREATE</title><content type='html'>Keep in mind, that on Windows top level window receives WM_GETMINMAXINFO message &lt;a href=http://www.cjr.org/resources/lc/priorto.php&gt;prior to&lt;/a&gt; WM_NCCREATE. Such behavior can be fatal for application that executes window initialization code in WM_NCCREATE message handler, since when receiving WM_GETMINMAXINFO window is not initialized yet.&lt;br /&gt;Oh, that cruel, stupid world...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5213006533208608117-2527321117118849524?l=wonder-mice.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wonder-mice.blogspot.com/feeds/2527321117118849524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wonder-mice.blogspot.com/2009/11/top-level-window-receives.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/2527321117118849524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/2527321117118849524'/><link rel='alternate' type='text/html' href='http://wonder-mice.blogspot.com/2009/11/top-level-window-receives.html' title='Top level window receives WM_GETMINMAXINFO before WM_NCCREATE'/><author><name>wonder.mice</name><uri>http://www.blogger.com/profile/04581796828247171007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5213006533208608117.post-7490446481039956909</id><published>2009-10-22T04:27:00.008+04:00</published><updated>2009-10-22T12:53:02.918+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Another good reason not to run program by its name in Windows</title><content type='html'>When searching for executable by its name Windows always looks in:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Current working directory&lt;/li&gt;&lt;li&gt;Windows system directory (use &lt;i&gt;GetSystemDirectory()&lt;/i&gt; to obtain it)&lt;/li&gt;&lt;li&gt;Windows directory (use &lt;i&gt;GetWindowsDirectory()&lt;/i&gt; to obtain it)&lt;/li&gt;&lt;li&gt;Directories listed in &lt;i&gt;PATH&lt;/i&gt; environment variable&lt;/li&gt;&lt;/ul&gt;This list (I will refer to it as &lt;i&gt;search directories&lt;/i&gt;) can be expanded with more directories when performing specific tasks.&lt;br /&gt;If &lt;i&gt;name&lt;/i&gt; does not contains file extension (for example &lt;i&gt;notepad&lt;/i&gt; or &lt;i&gt;attrib&lt;/i&gt;), Windows will use &lt;a href=http://en.wikipedia.org/wiki/Glob_%28programming%29&gt;glob&lt;/a&gt; &lt;i&gt;"name.*"&lt;/i&gt; to find file with extension that is listed in &lt;i&gt;PATHEXT&lt;/i&gt; environment variable.&lt;br /&gt;&lt;br /&gt;It's okay if you need just to run &lt;i&gt;notepad&lt;/i&gt; or &lt;i&gt;mspaint&lt;/i&gt; from command line. But what if you need to execute some program many times? Well, running it by its name is definitely not your choice. I'll try to explain why.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;First of all, one or more &lt;i&gt;search directories&lt;/i&gt; can contain very many files (30000 files for example). Second, one or more &lt;i&gt;search directories&lt;/i&gt; can be with slow access time (located on network share for example). If both is true, Windows will spend a lot of time just to locate executable to run. And the entire search will be performed again and again every time you ask Windows to execute something by its name.&lt;br /&gt;&lt;br /&gt;Here is a simple example. Lets write small &lt;i&gt;dotestiter.bat&lt;/i&gt; file and put it into &lt;i&gt;C:\Windows\System32 directory\&lt;/i&gt; (which is in &lt;i&gt;search directories&lt;/i&gt;):&lt;br /&gt;&lt;pre class='code-cpp'&gt;@dir /B %1&lt;/pre&gt;It can be executed by name (&lt;i&gt;dotestiter&lt;/i&gt;) or by its full path (&lt;i&gt;C:\Windows\System32\dotestiter.bat&lt;/i&gt;).&lt;br /&gt;We will call it from &lt;i&gt;dotest_name.bat&lt;/i&gt; file:&lt;br /&gt;&lt;pre class='code-cpp'&gt;@for /R %%e in (*) do dotestiter "%%e"&lt;/pre&gt;And from &lt;i&gt;dotest_full.bat&lt;/i&gt; file:&lt;br /&gt;&lt;pre class='code-cpp'&gt;@for /R %%e in (*) do C:\WINDOWS\system32\dotestiter.bat "%%e"&lt;/pre&gt;Both files will call &lt;i&gt;dotestiter.bat&lt;/i&gt; for every file in current working directory (current working directory is also in the &lt;i&gt;search directories&lt;/i&gt;).&lt;br /&gt;Results for network share with 250 files (I mounted it on &lt;i&gt;Z:&lt;/i&gt; with &lt;i&gt;net use&lt;/i&gt; to be able access it from command line):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;dotest_name.bat&lt;/i&gt; - &lt;b&gt;34.6 secs&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;dotest_full.bat&lt;/i&gt; - &lt;b&gt;24.3 secs&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;As you can see, it is much faster to use full executable path instead of its name. For 3000 files it will be required 2 minutes of &lt;b&gt;extra&lt;/b&gt; time just to locate the executable to run!&lt;br /&gt;&lt;br /&gt;p.s. It is hard to reproduce the same scenario on *nix since shell does not search current working directory for program name.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5213006533208608117-7490446481039956909?l=wonder-mice.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wonder-mice.blogspot.com/feeds/7490446481039956909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wonder-mice.blogspot.com/2009/10/another-good-reason-not-to-run-program.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/7490446481039956909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/7490446481039956909'/><link rel='alternate' type='text/html' href='http://wonder-mice.blogspot.com/2009/10/another-good-reason-not-to-run-program.html' title='Another good reason not to run program by its name in Windows'/><author><name>wonder.mice</name><uri>http://www.blogger.com/profile/04581796828247171007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5213006533208608117.post-2383427571429408459</id><published>2009-10-21T15:35:00.001+04:00</published><updated>2009-11-25T00:12:01.926+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><title type='text'>Dangerous logging</title><content type='html'>Today I will try to scare you:)&lt;br /&gt;The most common realization of logging is something like that (simplified):&lt;br /&gt;&lt;pre class='code-cpp'&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#ifdef _MSC_VER // workaround for MS VC&lt;br /&gt;#define snprintf(b, bsz, f, ...)                \&lt;br /&gt;        _snprintf_s(b, bsz, _TRUNCATE, f, __VA_ARGS__)&lt;br /&gt;#endif&lt;br /&gt;#define LOG_LEVEL 2&lt;br /&gt;#define LOG(lvl, ...) do {                       \&lt;br /&gt;    if (LOG_LEVEL &amp;lt; lvl) break;                  \&lt;br /&gt;    char b[1024];                                \&lt;br /&gt;    snprintf(b, sizeof(b) - 1, __VA_ARGS__);     \&lt;br /&gt;    b[sizeof(b) - 1] = 0;                        \&lt;br /&gt;    printf("%i! %s\n", (int)(lvl), b);           \&lt;br /&gt;} while(0 == __LINE__)&lt;/pre&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;It can be used in following way:&lt;br /&gt;&lt;pre class='code-cpp'&gt;unsigned fp;&lt;br /&gt;char *fname;&lt;br /&gt;// ...&lt;br /&gt;if (seekFailed)&lt;br /&gt;{&lt;br /&gt;    LOG(1, "Failed to seek to offset %u in file \"%s\"", fp, fname);&lt;br /&gt;}&lt;/pre&gt;Looks safe at first glance, probably you can find something similar in your project. But lets look deeper. One of the drawbacks of logging is that it does not perform any useful work and that it is always on the most rare execution path (because usually you want to log only errors or other uncommon events). Therefore, log messages are often not tested and forgotten (in some sense it is like code comments - nobody likes irrelevant comments, but it is not a problem to find one). As a result, you can find:&lt;br /&gt;&lt;pre class='code-cpp'&gt;LOG(1, "Failed to open file \"%s\", error %i", fname);&lt;/pre&gt;In that example, there is no error code passed (for &lt;i&gt;%i&lt;/i&gt;). Bad, but relatively harmless. Just some junk value from stack or register will be logged as error code. Or something worse:&lt;br /&gt;&lt;pre class='code-cpp'&gt;LOG(2, "Failed to rename \"%s\" to \"%s\"", oldName);&lt;/pre&gt;This example is very similar to previous one, except that junk from stack (or register, depending on calling convention used) will be used as pointer value (for second &lt;i&gt;%s&lt;/i&gt;). In most cases that will lead application to crash with access violation at address. We can get more interesting example by adding large files support in the first example (with &lt;i&gt;seekFailed&lt;/i&gt;). Variable &lt;i&gt;fp&lt;/i&gt; probably will be declared as:&lt;br /&gt;&lt;pre class='code-cpp'&gt;long long fp;&lt;/pre&gt;Oops, I will forget to replace &lt;i&gt;%u&lt;/i&gt; in:&lt;br /&gt;&lt;pre class='code-cpp'&gt;LOG(1, "Failed to seek to offset %u in file \"%s\"", fp, fname);&lt;/pre&gt;with something more appropriate (&lt;i&gt;%llu&lt;/i&gt;). To understand why it is better not to do so, lets look on how parameters are passed to function with variable arguments list. Depending on calling convention used, parameters are placed one after another into registers and stack. Not to count particular features of each calling convention, we'll consider that all parameters are placed in abstract cells of the same size arranged side by side. So, when compiler generates function call code for function with variable arguments list it doesn't know how passed parameters will be used. All it knows is type (and therefore size) of each parameter. It has nothing to do but just place all passed parameters one by another in those cells, side by side. Every parameter will get its own cell (or cells if parameter is too large to fit in one cell). Each cell will get only one parameter (or its part), it is not possible for cell to contain two or more parameters or several parts of different parameters. Called function has access to those cells. But curiosity of situation is that called function doesn't know anything about passed parameters (even total number of parameters is mystery for it). It just gets array of raw cells (without knowing total count of cells). There for, function with variable arguments list requires some extra information to be able to handle passed parameters. Most popular example of such information is format string in functions of &lt;i&gt;printf&lt;/i&gt; family, which contains rich information about passed parameters (type, total count and order is most important now). So, if that information about passed parameters is wrong, function will not be able to interpret content of cells properly (and therefor, entire program will not work properly). String &lt;i&gt;"Failed to seek to offset %u in file \"%s\""&lt;/i&gt; tells, that function will get two parameters - first of type &lt;i&gt;int&lt;/i&gt; and second of type &lt;i&gt;char *&lt;/i&gt;. In &lt;i&gt;IA-32&lt;/i&gt; (&lt;i&gt;i386&lt;/i&gt;) both of parameters require one 32-bit cell. What will be wrong if instead of first &lt;i&gt;int&lt;/i&gt; we'll pass &lt;i&gt;long long&lt;/i&gt;? Size of &lt;i&gt;long long&lt;/i&gt; in &lt;i&gt;IA-32&lt;/i&gt; is 64 bits. One cell will not enough for such large parameter, it will be placed in two adjacent cells, and second parameter (&lt;i&gt;char *&lt;/i&gt;) will be placed in third cell. When function will interpret cells content it will use first cell (with first 32-bit part of &lt;i&gt;fp&lt;/i&gt; variable) as first argument and second cell (with second 32-bit part of &lt;i&gt;fp&lt;/i&gt; variable) as second argument (that is of type &lt;i&gt;char *&lt;/i&gt;). The consequences of such mistake depends on value of &lt;i&gt;fp&lt;/i&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;if &lt;i&gt;UINT_MAX &amp;gt;= fp&lt;/i&gt;, the second part of &lt;i&gt;fp&lt;/i&gt; variable will be zero (it is enough 32 bits to represent numbers from 0 to &lt;i&gt;UINT_MAX&lt;/i&gt;) and string &lt;i&gt;"(null)"&lt;/i&gt; will be logged instead of file name&lt;/li&gt;&lt;li&gt;if &lt;i&gt;UINT_MAX &amp;lt; fp&lt;/i&gt;, then second part of &lt;i&gt;fp&lt;/i&gt; variable will be non-zero (probably it will not be a correct pointer on the allocated memory) and application will crash with access violation at address&lt;/li&gt;&lt;/ul&gt;Under &lt;i&gt;AMD64&lt;/i&gt; (&lt;i&gt;x86-64&lt;/i&gt;) size of cell is 64 bits. Therefor every parameter will get exactly one cell (first cell for first parameter and second cell for second parameter), as it was supposed. But only 32-bit part of &lt;i&gt;fp&lt;/i&gt; will be logged, since function still thinks that first cell contains &lt;i&gt;int&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Yeh, such a horror story.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5213006533208608117-2383427571429408459?l=wonder-mice.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wonder-mice.blogspot.com/feeds/2383427571429408459/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wonder-mice.blogspot.com/2009/10/dangerous-logging.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/2383427571429408459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/2383427571429408459'/><link rel='alternate' type='text/html' href='http://wonder-mice.blogspot.com/2009/10/dangerous-logging.html' title='Dangerous logging'/><author><name>wonder.mice</name><uri>http://www.blogger.com/profile/04581796828247171007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5213006533208608117.post-201746971685480742</id><published>2009-10-05T14:17:00.004+04:00</published><updated>2009-10-05T14:37:00.583+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PE'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Platforms'/><title type='text'>Whether this windows binary is 32- or 64-bit?</title><content type='html'>The fastest way to answer on this question without using special software tools is:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Open windows binary file in any text/hex editor (notepad is enough)&lt;/li&gt;&lt;li&gt;Find first occurrence of "PE" string (it will be probably placed at offset 0xD0, 0xF0 or something like that after phrase "This program cannot be run in DOS mode")&lt;/li&gt;&lt;li&gt;Skip 2 non-printable symbols (both '\0')&lt;/li&gt;&lt;li&gt;Look on the symbol you are at:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;'L'&lt;/b&gt; - i386 binary (x86)&lt;/li&gt;&lt;li&gt;&lt;b&gt;'d'&lt;/b&gt; - amd64 binary (x64/x86-64)&lt;/li&gt;&lt;li&gt;&lt;b&gt;'\0'&lt;/b&gt; (zero) - ia64 binary&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;p.s. You can use that method for any PE binary (like .exe, .dll and others)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5213006533208608117-201746971685480742?l=wonder-mice.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wonder-mice.blogspot.com/feeds/201746971685480742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wonder-mice.blogspot.com/2009/10/whether-this-windows-binary-is-32-or-64.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/201746971685480742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/201746971685480742'/><link rel='alternate' type='text/html' href='http://wonder-mice.blogspot.com/2009/10/whether-this-windows-binary-is-32-or-64.html' title='Whether this windows binary is 32- or 64-bit?'/><author><name>wonder.mice</name><uri>http://www.blogger.com/profile/04581796828247171007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5213006533208608117.post-3333832686228679637</id><published>2009-10-03T01:45:00.016+04:00</published><updated>2009-10-04T22:24:04.891+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Games'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Games: static stuff</title><content type='html'>Even the most simple thing can confuse sometimes. Usually this happens because of lack of particular experience. How to obtain such experience? Well, of course to play!&lt;br /&gt;&lt;br /&gt;&lt;i&gt;I hope it will be not the last post in that blog. Under the heading "Games" I am going to talk about things that you have always wanted to try, but because of laziness or high employment always were afraid to do it. So, let's play!&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Today I want to play with static data in C++.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;The theoretical conception of static data, and how it should be used can be obtained by reading the first &lt;i&gt;N&lt;/i&gt; links on request &lt;a href = http://www.google.com/search?q=static+keyword+[C%2B%2B]&gt;static keyword [C++]&lt;/a&gt;. So, lets move to practice right now.&lt;br /&gt;&lt;br /&gt;In my experiments I will use simple class, that will print string in its constructor and destructor. Printed string is passed as argument for constructor:&lt;br /&gt;&lt;pre style="margin-left: 20px; line-height: 100%; font-family: Courier New; font-size: 90%; color: green;"&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;class CThing&lt;br /&gt;{&lt;br /&gt;    CThing();&lt;br /&gt;    const char *const m_name;&lt;br /&gt;public:&lt;br /&gt;    CThing(const char *const name): m_name(name)&lt;br /&gt;    { printf("CThing::CThing(\"%s\")\n", name); }&lt;br /&gt;    ~CThing()&lt;br /&gt;    { printf("CThing::~CThing(\"%s\")\n", m_name); }&lt;br /&gt;    void echo() const { printf("echo from \"%s\"\n", m_name);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;For the beginning, lets figure out when constructor and destructor of a static variables are called:&lt;br /&gt;&lt;pre style="margin-left: 20px; line-height: 100%; font-family: Courier New; font-size: 90%; color: green;"&gt;void someProc1()&lt;br /&gt;{&lt;br /&gt;    static CThing thing("thing in someProc1");&lt;br /&gt;}&lt;br /&gt;CThing thing1("thing1");&lt;br /&gt;int main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;    (void)argc; (void)argv;&lt;br /&gt;    printf("---- main() ----\n");&lt;br /&gt;    someProc1();&lt;br /&gt;    someProc1();&lt;br /&gt;    printf("---- return ----\n");&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;After executing the program:&lt;br /&gt;&lt;pre style="margin-left: 20px; line-height: 100%; font-family: Courier New; font-size: 90%; background-color: grey; color: white; border: 1px dotted black;"&gt;CThing::CThing("thing1")&lt;br /&gt;---- main() ----&lt;br /&gt;CThing::CThing("thing in someProc1")&lt;br /&gt;---- return ----&lt;br /&gt;CThing::~CThing("thing in someProc1")&lt;br /&gt;CThing::~CThing("thing1")&lt;br /&gt;&lt;/pre&gt;As you can see, &lt;i&gt;"thing in someProc1"&lt;/i&gt; actually created at the time of the first call to &lt;i&gt;someProc1()&lt;/i&gt;. Destructors as it should be, are called in reverse order of constructor calls. Some people do not fully understand how static variables work, and therefore give the compiler different magical abilities. In fact, there is no magic of course. Static variable definition:&lt;br /&gt;&lt;pre style="margin-left: 20px; line-height: 100%; font-family: Courier New; font-size: 90%; color: green;"&gt;void someProc1()&lt;br /&gt;{&lt;br /&gt;    static CThing thing("thing");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;compiler will translate into something like this:&lt;br /&gt;&lt;pre style="margin-left: 20px; line-height: 100%; font-family: Courier New; font-size: 90%; color: green;"&gt;bool g_thingInitialized = false;&lt;br /&gt;CThing *g_thingPtr;&lt;br /&gt;void g_thingDelete() { delete g_thingPtr; }&lt;br /&gt;void someProc1()&lt;br /&gt;{&lt;br /&gt;    if (!g_thingInitialized)&lt;br /&gt;    {&lt;br /&gt;        g_thingInitialized = true;&lt;br /&gt;        g_thingPtr = new CThing("thing");&lt;br /&gt;        atexit(g_thingDelete);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Like that easy. And because of such a simple realization of static variables, there are two issues (which are described in detail in &lt;a href=http://blogs.msdn.com/oldnewthing/archive/2004/03/08/85901.aspx&gt;C++ scoped static initialization is not thread-safe, on purpose!&lt;/a&gt;):&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Contrary to popular opinion, the fact that the static variable is initialized will be checked each time function is called.&lt;/li&gt;&lt;li&gt;It is not thread-safe to use static variables. The compiler does not know anything about threads and does not provide any synchronization when initializing static variables. Thus, multiple instances of the class CThing can be created (plus a whole bunch of troubles, which you can get, hoping that all synchronization work will be done by compiler).&lt;/li&gt;&lt;/ol&gt;Now lets look at static class members:&lt;br /&gt;&lt;pre style="margin-left: 20px; line-height: 100%; font-family: Courier New; font-size: 90%; color: green;"&gt;class CBigThing&lt;br /&gt;{&lt;br /&gt;    static CThing m_thing;&lt;br /&gt;    const char *const m_name;&lt;br /&gt;public:&lt;br /&gt;    CBigThing(const char *const name): m_name(name)&lt;br /&gt;    { printf("CBigThing::CBigThing(\"%s\")\n", name); }&lt;br /&gt;    ~CBigThing()&lt;br /&gt;    { printf("CBigThing::~CBigThing(\"%s\")\n", m_name); }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;class CAnyThing&lt;br /&gt;{&lt;br /&gt;    static CThing m_thing;&lt;br /&gt;    const char *const m_name;&lt;br /&gt;public:&lt;br /&gt;    CAnyThing(const char *const name): m_name(name)&lt;br /&gt;    { printf("CAnyThing::CAnyThing(\"%s\")\n", name); }&lt;br /&gt;    ~CAnyThing()&lt;br /&gt;    { printf("CAnyThing::~CAnyThing(\"%s\")\n", m_name); }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;CThing CAnyThing::m_thing("m_thing from CAnyThing");&lt;br /&gt;CThing thing1("thing1");&lt;br /&gt;CThing CBigThing::m_thing("m_thing from CBigThing");&lt;br /&gt;&lt;br /&gt;int main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;    (void)argc; (void)argv;&lt;br /&gt;    printf("---- main() ----\n");&lt;br /&gt;    CBigThing bigThing("bigThing");&lt;br /&gt;    printf("---- return ----\n");&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Program will print:&lt;br /&gt;&lt;pre style="margin-left: 20px; line-height: 100%; font-family: Courier New; font-size: 90%; background-color: grey; color: white; border: 1px dotted black;"&gt;CThing::CThing("m_thing from CAnyThing")&lt;br /&gt;CThing::CThing("thing1")&lt;br /&gt;CThing::CThing("m_thing from CBigThing")&lt;br /&gt;---- main() ----&lt;br /&gt;CBigThing::CBigThing("bigThing")&lt;br /&gt;---- return ----&lt;br /&gt;CBigThing::~CBigThing("bigThing")&lt;br /&gt;CThing::~CThing("m_thing from CBigThing")&lt;br /&gt;CThing::~CThing("thing1")&lt;br /&gt;CThing::~CThing("m_thing from CAnyThing")&lt;br /&gt;&lt;/pre&gt;As you can see, static class members are not created with the first instance of a class (as one would assume). They are created with other global variables in the order of their definition (and destroyed in the reverse order).&lt;br /&gt;&lt;br /&gt;It is worth noting that the order of initialization of global variables exactly known only for variables defined in the scope of one file (module). The order of initialization of global variables in different files is not defined and depends on factors, which you probably do not want to rely on. Here is a good example of what can happen if you carelessly use global variables within different files:&lt;br /&gt;&lt;pre style="margin-left: 20px; line-height: 100%; font-family: Courier New; font-size: 90%; color: green;"&gt;&lt;b&gt;// it CAN be in file actions.cpp:&lt;/b&gt;&lt;br /&gt;extern CThing thingA;&lt;br /&gt;extern CThing thingB;&lt;br /&gt;&lt;br /&gt;bool doThings()&lt;br /&gt;{&lt;br /&gt;    thingA.echo();&lt;br /&gt;    thingB.echo();&lt;br /&gt;    return true;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;bool doneThings = doThings();&lt;br /&gt;&lt;br /&gt;&lt;b&gt;// it CAN be in file things.cpp:&lt;/b&gt;&lt;br /&gt;CThing thingA("thingA");&lt;br /&gt;CThing thingB("thingB");&lt;br /&gt;&lt;br /&gt;&lt;b&gt;// it CAN be in file main.cpp:&lt;/b&gt;&lt;br /&gt;int main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;    (void)argc; (void)argv;&lt;br /&gt;    printf("---- main() ----\n");&lt;br /&gt;    printf("---- return ----\n");&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Output will be:&lt;br /&gt;&lt;pre style="margin-left: 20px; line-height: 100%; font-family: Courier New; font-size: 90%; background-color: grey; color: white; border: 1px dotted black;"&gt;echo from "(null)"&lt;br /&gt;echo from "(null)"&lt;br /&gt;CThing::CThing("thingA")&lt;br /&gt;CThing::CThing("thingB")&lt;br /&gt;---- main() ----&lt;br /&gt;---- return ----&lt;br /&gt;CThing::~CThing("thingB")&lt;br /&gt;CThing::~CThing("thingA")&lt;br /&gt;&lt;/pre&gt;Objects &lt;i&gt;thingA&lt;/i&gt; and &lt;i&gt;thingB&lt;/i&gt; where used uninitialized. When the code is located in a single file, the reason of such behavior is obvious - &lt;i&gt;doneThings&lt;/i&gt; is defined before &lt;i&gt;thingA&lt;/i&gt; and &lt;i&gt;thingB&lt;/i&gt;. However, if you split the code on files &lt;i&gt;actions.cpp&lt;/i&gt;, &lt;i&gt;things.cpp&lt;/i&gt; and &lt;i&gt;main.cpp&lt;/i&gt; (as indicated in the comments), then the situation becomes more interesting. The program can begin to work as required and print:&lt;br /&gt;&lt;pre style="margin-left: 20px; line-height: 100%; font-family: Courier New; font-size: 90%; background-color: grey; color: white; border: 1px dotted black;"&gt;CThing::CThing("thingA")&lt;br /&gt;CThing::CThing("thingB")&lt;br /&gt;echo from "thingA"&lt;br /&gt;echo from "thingB"&lt;br /&gt;---- main() ----&lt;br /&gt;---- return ----&lt;br /&gt;CThing::~CThing("thingB")&lt;br /&gt;CThing::~CThing("thingA")&lt;br /&gt;&lt;/pre&gt;But maybe not. Depends on the implementation of the compiler used (its version, the name of source files, the order in which files specified in the compiler command line, ...). I guess no one wants to have a program that can stop working after adding a new file or renaming the existing one.&lt;br /&gt;&lt;br /&gt;Ok, I thing it's enough for beginning :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5213006533208608117-3333832686228679637?l=wonder-mice.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wonder-mice.blogspot.com/feeds/3333832686228679637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wonder-mice.blogspot.com/2009/10/even-most-simple-thing-can-confuse.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/3333832686228679637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/3333832686228679637'/><link rel='alternate' type='text/html' href='http://wonder-mice.blogspot.com/2009/10/even-most-simple-thing-can-confuse.html' title='Games: static stuff'/><author><name>wonder.mice</name><uri>http://www.blogger.com/profile/04581796828247171007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5213006533208608117.post-3530133336988947835</id><published>2009-10-01T19:31:00.001+04:00</published><updated>2009-10-03T02:26:30.312+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dummy'/><title type='text'>Ping Post</title><content type='html'>Meaningless post just to see that all that stuff called blogger.com works.&lt;br /&gt;I don't have any super original idea for the first post, so let it be just a "ping" post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5213006533208608117-3530133336988947835?l=wonder-mice.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://wonder-mice.blogspot.com/feeds/3530133336988947835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://wonder-mice.blogspot.com/2009/10/ping-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/3530133336988947835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5213006533208608117/posts/default/3530133336988947835'/><link rel='alternate' type='text/html' href='http://wonder-mice.blogspot.com/2009/10/ping-post.html' title='Ping Post'/><author><name>wonder.mice</name><uri>http://www.blogger.com/profile/04581796828247171007</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
