<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-833174317742362874</atom:id><lastBuildDate>Tue, 14 May 2013 08:09:50 +0000</lastBuildDate><category>strlcpy</category><category>Portability</category><category>flash</category><category>Dolphin</category><category>lighttpd</category><category>File Dialog</category><category>file descriptor</category><category>bugs</category><category>fgets</category><category>competition</category><category>Windows</category><category>open source</category><category>binary</category><category>variadic templates</category><category>HTTP</category><category>FatELF</category><category>GCC</category><category>PHB</category><category>iphone</category><category>searching</category><category>Mac OS X</category><category>PC</category><category>C++ 2011</category><category>lambda functions</category><category>insane ideas</category><category>BIOS</category><category>torture</category><category>SSH</category><category>standards compliance</category><category>readdir</category><category>parameters</category><category>language</category><category>Hashing</category><category>fstatat</category><category>school</category><category>Blogger</category><category>coreutils</category><category>opendir</category><category>__func__</category><category>Antisemitism</category><category>fcntl</category><category>compatibility</category><category>Firefox</category><category>getcwd</category><category>MSVC</category><category>Qt</category><category>buffer overflow</category><category>c99</category><category>factory</category><category>tree</category><category>Optimization</category><category>x86-64</category><category>recursion</category><category>unsigned</category><category>stat</category><category>Function Pointers</category><category>pure failure</category><category>secure</category><category>Cfront</category><category>modconf</category><category>x86</category><category>directory</category><category>good code</category><category>gnu</category><category>protocols</category><category>ManyMouse</category><category>export</category><category>BSD</category><category>closed source</category><category>OSS</category><category>GNOME</category><category>types</category><category>C++-0x</category><category>GUI</category><category>GTK</category><category>realpath</category><category>Mozilla</category><category>Trolltech</category><category>debian</category><category>Ancient Coding Ideas</category><category>strlmrg</category><category>CPU Detection</category><category>linux</category><category>apache</category><category>bad code</category><category>KDE</category><category>non rectangular array</category><category>PATH_MAX</category><category>quicksort</category><category>signed</category><category>fchmod</category><category>C++-201x</category><category>gzdirect</category><category>openat</category><category>Library</category><category>sorting</category><category>ftruncate</category><category>files</category><category>multicore</category><category>discrimination</category><category>gets</category><category>strlcat</category><category>API</category><category>Google</category><category>tar</category><category>ALSA</category><category>crazy executives</category><category>Political Correctness</category><category>initializer lists</category><category>multiseat</category><category>code search</category><category>save_cwd</category><category>gzdopen</category><category>Television</category><category>distribution</category><title>Insane Coding</title><description>'coz good thinking requires going outside the box</description><link>http://insanecoding.blogspot.com/</link><managingEditor>noreply@blogger.com (insane coder)</managingEditor><generator>Blogger</generator><openSearch:totalResults>61</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-5154274617004024762</guid><pubDate>Wed, 03 Apr 2013 01:09:00 +0000</pubDate><atom:updated>2013-04-03T06:56:58.221-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>files</category><category domain='http://www.blogger.com/atom/ns#'>Function Pointers</category><category domain='http://www.blogger.com/atom/ns#'>Library</category><category domain='http://www.blogger.com/atom/ns#'>file descriptor</category><category domain='http://www.blogger.com/atom/ns#'>insane ideas</category><category domain='http://www.blogger.com/atom/ns#'>C++-0x</category><category domain='http://www.blogger.com/atom/ns#'>protocols</category><category domain='http://www.blogger.com/atom/ns#'>C++ 2011</category><category domain='http://www.blogger.com/atom/ns#'>good code</category><category domain='http://www.blogger.com/atom/ns#'>compatibility</category><category domain='http://www.blogger.com/atom/ns#'>API</category><category domain='http://www.blogger.com/atom/ns#'>binary</category><category domain='http://www.blogger.com/atom/ns#'>lambda functions</category><category domain='http://www.blogger.com/atom/ns#'>Portability</category><category domain='http://www.blogger.com/atom/ns#'>language</category><category domain='http://www.blogger.com/atom/ns#'>Optimization</category><title>Designing C++ functions to write/save to any storage mechanism</title><description>&lt;h3 style="text-align: center;"&gt;Problem&lt;/h3&gt;A common issue when dealing with a custom object or any kind of data is to create some sort of save functionality with it, perhaps writing some text or binary to a file. So what is the correct C++ method to allow an object to save its data &lt;u&gt;anywhere&lt;/u&gt;?&lt;br /&gt;&lt;br /&gt;An initial approach to allow some custom object to be able to save its data to a file is to create a member function like so: &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;void save(const char *filename);&lt;/pre&gt;&lt;/blockquote&gt;While this is perfectly reasonable, what if I want something more advanced than that? Say I don't want the data to be saved as its own separate file, but would rather the data be written to some file that is already open, to a particular location within it? What if I'd rather save the data to a database? How about send the data over the network?&lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;"&gt;Naive Approach&lt;/h3&gt;&lt;br /&gt;When C++ programmers hear the initial set of requirements, they generally look to one of two solutions:&lt;br /&gt;&lt;br /&gt;The first is to allow for a save function which can take an &lt;i&gt;std::ostream&lt;/i&gt;, like so: &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;void save(std::ostream &amp;amp;stream);&lt;/pre&gt;&lt;/blockquote&gt;C++ out of the box offers &lt;i&gt;std::cout&lt;/i&gt; as an instance of an &lt;i&gt;std::ostream&lt;/i&gt; which writes to the screen. C++ offers a derived class &lt;i&gt;std::ofstream&lt;/i&gt; (&lt;i&gt;std::fstream&lt;/i&gt;) which can save to files on disk. C++ also offers a derived class &lt;a href="http://en.cppreference.com/w/cpp/io/basic_ostringstream" target="_blank"&gt;std::ostringstream&lt;/a&gt; which saves file to a C++ string.&lt;br /&gt;&lt;br /&gt;With these options, you can display the data on the screen, save it to an actual file, or save it to a string, which you can then in turn save it wherever you want.&lt;br /&gt;&lt;br /&gt;The next option programmers look to is to overload&amp;nbsp; &lt;a href="http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt" target="_blank"&gt;&lt;i&gt;std::basic_ostream::operator&amp;lt;&amp;lt;&lt;/i&gt;&lt;/a&gt; for the custom object. This way one can simply write:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;mystream &amp;lt;&amp;lt; myobject;&lt;/pre&gt;&lt;/blockquote&gt;And then the object can be written to any C++ stream.&lt;br /&gt;&lt;br /&gt;Either of these techniques pretty much work, but can be a bit annoying when you want a lot of flexibility &lt;b&gt;and&lt;/b&gt; performance.&lt;br /&gt;&lt;br /&gt;Say I wanted to save my object over the network, what do I do? I could save it to a string stream, grab the string, and then send that over the network, even though that seems a bit wasteful.&lt;br /&gt;&lt;br /&gt;And for a similar case, say I have an already open &lt;a href="http://en.wikipedia.org/wiki/File_descriptor" target="_blank"&gt;file descriptor&lt;/a&gt;, and wish to save my object to it, do I also use a string stream as an intermediary?&lt;br /&gt;&lt;br /&gt;Since C++ is extensible, one could actually create their own &lt;a href="http://en.cppreference.com/w/cpp/io/basic_streambuf" target="_blank"&gt;std::basic_streambuf&lt;/a&gt; derived class which works with file descriptors, and attach it to an std::ostream, which can then be used with anything that works with a stream for output. I'm not going to go into the details how to do that here, but &lt;a href="http://www.amazon.com/gp/product/0321623215/ref=as_li_qf_sp_asin_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0321623215&amp;amp;linkCode=as2&amp;amp;tag=insacodi-20"&gt;The C++ Standard Library&lt;/a&gt;&lt;img alt="" border="0" class="hioyqmdriwomkxxppfkw" height="1" src="http://www.assoc-amazon.com/e/ir?t=insacodi-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0321623215" style="border: none !important; margin: 0px !important;" width="1" /&gt; explains the general idea, and provides a working &lt;i&gt;file descriptor streambuf&lt;/i&gt; example and shows how to use it with stream functions. You can also find some ready made implementations online with a bit of searching, and some compilers may even include a solution out of the box in their C++ extensions.&lt;br /&gt;&lt;br /&gt;On UNIX systems, once you have a stream which works with file descriptors, you can now send data over the network, as sockets themselves are file descriptors. On Windows, you'll need a separate class which works with &lt;i&gt;SOCKET&lt;/i&gt;s. Of course to turn a &lt;i&gt;file descriptor streambuf&lt;/i&gt; into a &lt;i&gt;SOCKET&lt;/i&gt; &lt;i&gt;streambuf&lt;/i&gt; is trivial, and can probably be done with a few well crafted search and replace commands.&lt;br /&gt;&lt;br /&gt;Now this may have solved the extra string overhead with file descriptors and networking, but what about if I want to save to a database? What about if I'm working with C's &lt;i&gt;FILE *&lt;/i&gt;? Does one now have to implement a new wrapper for each of these (or pray the compiler offers an extension, or one can be found online)? The C++ stream library is actually a bit bloaty, and creating your own streambufs is somewhat annoying, especially if you want to do it right and allow for buffering. Many stream related library code you find online are also of poor quality. Surely there must be a better option, right?&lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;"&gt;Solution&lt;/h3&gt;&lt;br /&gt;If we look back at how C handles this problem, it uses &lt;a href="http://insanecoding.blogspot.com/2007/05/secrets-to-optimization-function.html" target="_blank"&gt;function pointers&lt;/a&gt;, where the function doing the writing receives a callback to use for the actual writing, and the programmer using it can make the writing go anywhere. C++ of course includes this ability, and even takes it much further, in the form of &lt;a href="http://en.wikipedia.org/wiki/Function_object" target="_blank"&gt;function objects&lt;/a&gt;, and even further in C++ 2011.&lt;br /&gt;&lt;br /&gt;Let's start with an example.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;template&amp;lt;typename WriteFunction&amp;gt;&lt;br /&gt;void world(WriteFunction func)&lt;br /&gt;{&lt;br /&gt;  //Do some stuff...&lt;br /&gt;  //Do some more stuff...&lt;br /&gt;  func("World", 5); //Write 5 characters via callback&lt;br /&gt;  //Do some more stuff...&lt;br /&gt;  unsigned char *data = ...;&lt;br /&gt;  func(data, data_size); //Write some bytes&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;The template function above is expecting any function pointer which can be used to write data by passing it a pointer and a length. A proper signature would be something like the following: &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;void func(const void *data, size_t length);&lt;/pre&gt;&lt;/blockquote&gt;Creating such a function is trivial. However, to be useful, writing needs to also include a destination of some sort, a device, a file, a database row, and so on, which makes function objects more powerful.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;&lt;br /&gt;class writer_file&lt;br /&gt;{&lt;br /&gt;  std::FILE *handle;&lt;br /&gt;  public:&lt;br /&gt;  writer_file(std::FILE *handle) : handle(handle) {}&lt;br /&gt;  inline void operator()(const void *data, size_t length)&lt;br /&gt;  {&lt;br /&gt;    std::fwrite(data, 1, length, handle);&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Which can be used as follows: &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;world(writer_file(stdout));&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Or perhaps: &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;std::FILE *fp = fopen("somefile.bin", "wb");&lt;br /&gt;world(writer_file(fp));&lt;br /&gt;std::close(fp);&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;As can be seen, our World function can write to any &lt;i&gt;FILE *&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;To allow any &lt;i&gt;char-based&lt;/i&gt; stream to be written, the following function object will do the trick:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;ostream&amp;gt;&lt;br /&gt;&lt;br /&gt;class writer_stream&lt;br /&gt;{&lt;br /&gt;  std::ostream *handle;&lt;br /&gt;  public:&lt;br /&gt;  writer_stream(std::ostream &amp;amp;handle) : handle(&amp;amp;handle) {}&lt;br /&gt;  inline void operator()(const void *data, size_t length)&lt;br /&gt;  {&lt;br /&gt;    handle-&amp;gt;write(reinterpret_cast&amp;lt;const char *&amp;gt;(data), length);&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;You can call this with: &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;world(writer_stream(std::cout));&lt;/pre&gt;&lt;/blockquote&gt;Or anything in the &lt;a href="http://www.cplusplus.com/reference/ostream/ostream/" target="_blank"&gt;ostream family&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If for some reason we wanted to write to strings, it's easy to create a function object for them too, and we can use the string directly without involving a string stream.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;&lt;br /&gt;class writer_string&lt;br /&gt;{&lt;br /&gt;  std::string *handle;&lt;br /&gt;  public:&lt;br /&gt;  writer_string(std::string &amp;amp;handle) : handle(&amp;amp;handle) {}&lt;br /&gt;  inline void operator()(const void *data, size_t length)&lt;br /&gt;  {&lt;br /&gt;    handle-&amp;gt;append(reinterpret_cast&amp;lt;const char *&amp;gt;(data), length);&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;If you're worried about function objects being slow, then don't. Passing a function object like this to a template function has no overhead. The compiler is able to see a series of direct calls, and throws all the extraneous details away. It is as if the body of World is calling the write function to the handle passed to it directly. For more information, see &lt;a href="http://www.amazon.com/gp/product/0201749629/ref=as_li_tf_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0201749629&amp;amp;linkCode=as2&amp;amp;tag=insacodi-20"&gt;Effective STL&lt;/a&gt;&lt;img alt="" border="0" class="hioyqmdriwomkxxppfkw" height="1" src="http://www.assoc-amazon.com/e/ir?t=insacodi-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0201749629" style="border: none !important; margin: 0px !important;" width="1" /&gt; Item 46.&lt;br /&gt;&lt;br /&gt;If you're wondering why developers forgo function pointers and function objects for situations like this, it is because  C++ offers so much with its stream classes, which are also very  extensible (and are often extended), they completely forget there are  other options. The stream classes are also designed for formatting output, and working with all kinds of special objects. But if you just need raw writing or saving of data, the stream classes are overkill.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;"&gt;C++ 2011&lt;/h3&gt;&lt;br /&gt;Now C++ 2011 extends all this further in a multiple of ways.&lt;br /&gt;&lt;br /&gt;&lt;h4 style="text-align: center;"&gt;std::bind()&lt;/h4&gt;&lt;br /&gt;First of all, C++ 2011 offers &lt;a href="http://en.cppreference.com/w/cpp/utility/functional/bind" target="_blank"&gt;std::bind()&lt;/a&gt; which allows for creating function object adapters on the fly. std::bind() can take an unlimited amount of parameters. The first must be a function pointer of some sort, the next is optionally an object to work on in the case of a &lt;a href="http://www.parashift.com/c++-faq/pointers-to-members.html" target="_blank"&gt;member function pointer&lt;/a&gt;, followed by the parameters to the function. These parameters can be hard coded by the caller, or bound via placeholders by the callee.&lt;br /&gt;&lt;br /&gt;Here's how you would use std::bind() for using fwrite():&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;functional&amp;gt;&lt;br /&gt;world(std::bind(std::fwrite, std::placeholders::_1, 1, std::placeholders::_2, stdout));&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Let us understand what is happening here. The function being called is std::fwrite(). It has 4 parameters. It's first parameter is the first parameter by the callee, denoted by &lt;i&gt;std::placeholders::_1&lt;/i&gt;. The second parameter is being hard coded to 1 by the caller. The third parameter is the second parameter from the callee denoted by &lt;i&gt;std::placeholders::_2&lt;/i&gt;. The fourth parameter is being hardcoded by the caller to stdout. It could be set to any &lt;i&gt;FILE *&lt;/i&gt; as needed by the caller.&lt;br /&gt;&lt;br /&gt;Now we'll see how this works with objects. To use with a stream, the basic approach is as follows:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;world(std::bind(&amp;amp;std::ostream::write, &amp;amp;std::cout, std::placeholders::_1, std::placeholders::_2));&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Note how we're turning a member function into a pointer, and we're also turning &lt;i&gt;cout&lt;/i&gt; into a pointer so it can be passed as &lt;i&gt;std::ostream::write&lt;/i&gt;'s &lt;i&gt;this&lt;/i&gt; pointer. The callee will pass its first and second parameters as the parameters to the stream write function.  However, the above has a slight flaw, it will only work if writing is done with &lt;i&gt;char *&lt;/i&gt; data. We can solve that with casting. &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;world(std::bind(reinterpret_cast&amp;lt;void (std::ostream::*)(const void *, size_t)&amp;gt;(&amp;amp;std::ostream::write), &amp;amp;std::cout, std::placeholders::_1, std::placeholders::_2));&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Take a moment to notice that we're not just casting it to the needed function pointer, but as a member function pointer of &lt;i&gt;std::ostream&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;You might find doing this a bit more comfortable than using classical function objects. However, function objects still have their place, wherever functions do. Remember, functions are about re-usability, and some scenarios are complicated enough that you want to pull out a full blown function object.&lt;br /&gt;&lt;br /&gt;For working with file descriptors, you might be tempted to do the following:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;world(std::bind(::write, 1, std::placeholders::_1, std::placeholders::_2));&lt;/pre&gt;&lt;/blockquote&gt;This here will have World write to file descriptor 1 - generally standard output. However this simple design is a mistake. &lt;a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html"&gt;Write&lt;/a&gt; can be interrupted by signals and needs to be resumed manually (by default, except on Solaris), among other issues, especially if the file descriptor is some kind of pipe or a socket. A proper write would be along the following lines: &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;system_error&amp;gt;&lt;br /&gt;#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;&lt;br /&gt;class writer_fd&lt;br /&gt;{&lt;br /&gt;  int handle;&lt;br /&gt;  public:&lt;br /&gt;  writer_fd(int handle) : handle(handle) {}&lt;br /&gt;  inline void operator()(const void *data, size_t length)&lt;br /&gt;  {&lt;br /&gt;    while (length)&lt;br /&gt;    {&lt;br /&gt;      ssize_t r = ::write(handle, data, length);&lt;br /&gt;      if (r &amp;gt; 0) { data = static_cast&amp;lt;const char *&amp;gt;(data)+r; length -= r; }&lt;br /&gt;      else if (!r) { break; }&lt;br /&gt;      else if (errno != EINTR) { throw std::system_error(errno, std::system_category()); }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;};&lt;/pre&gt;&lt;/blockquote&gt;&lt;h4 style="text-align: center;"&gt;Lambda Functions &lt;/h4&gt;Now you might be wondering, why C++ 2011 stopped with std::bind(), what if the function body needs more than just a single function call that can be wrapped up in an adapter? That's where lambda functions come in. &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;world([&amp;amp;](const void *data, size_t length){ std::fwrite(data, 1, length, stdout); });&lt;br /&gt;world([&amp;amp;](const void *data, size_t length){ std::cout.write(static_cast&amp;lt;const char *&amp;gt;(data), length); });&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Note the ridiculous syntax. The &lt;i&gt;[](){}&lt;/i&gt; combination signifies we are working with a lambda function. The &lt;i&gt;[]&lt;/i&gt; receives a function scope, in this case &lt;i&gt;&amp;amp;&lt;/i&gt;, which means that the function operates fully within its parent-scope, and has direct access to all its data. The rest you should already be well familiar with. You can change the &lt;i&gt;stdout&lt;/i&gt; or the &lt;i&gt;cout&lt;/i&gt; in the body of the lambda function to use your &lt;i&gt;FILE *&lt;/i&gt; or &lt;i&gt;ostream&lt;/i&gt; as necessary.&lt;br /&gt;&lt;br /&gt;Let us look at an example of having our World function write directly to a buffer. &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;cstring&amp;gt;&lt;br /&gt;&lt;br /&gt;void *p = ...; //Point p at some buffer which has enough room to hold the contents needed to be written to it.&lt;br /&gt;world([&amp;amp;](const void *data, size_t length){ std::memcpy(p, data, length); p = static_cast&amp;lt;char *&amp;gt;(p) + length; });&lt;/pre&gt;&lt;/blockquote&gt;There's a very important point in this example. There is a pointer which is initialized to where writing should begin. Every time data is written, the pointer is incremented. This ensures that if World calls the passed write function multiple times, it will continue to work correctly. This was not needed for files above, as their write pointer increments automatically, or with &lt;i&gt;std::string&lt;/i&gt;, where &lt;i&gt;append&lt;/i&gt; always writes to the end, wherever it now is.&lt;br /&gt;&lt;br /&gt;Be careful writing like this though, you must ensure in advance that your buffer is large enough, perhaps if your object has a way of reporting how much data the next call to its save or write function needs to generate. If it doesn't and you're winging it, something like the following is in order:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;stdexcept&amp;gt;&lt;br /&gt;&lt;br /&gt;class writer_buffer&lt;br /&gt;{&lt;br /&gt;  void *handle, *limit;&lt;br /&gt;  public:&lt;br /&gt;  writer_buffer(void *handle, size_t limit) : handle(handle), limit(static_cast&lt;char&gt;(handle)+limit) {}&lt;br /&gt;  inline void operator()(const void *data, size_t length)&lt;br /&gt;  {&lt;br /&gt;    if ((static_cast&amp;lt;char *&amp;gt;(handle) + length) &amp;gt; limit) { throw std::out_of_range("writer_buffer"); }&lt;br /&gt;    std::memcpy(handle, data, length);&lt;br /&gt;    handle = static_cast&amp;lt;char *&amp;gt;(handle) + length;&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;/char&gt;&lt;/pre&gt;&lt;/blockquote&gt;You can use it as follows: &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;#include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;&lt;br /&gt;size_t amount = 1024; //A nice number!&lt;br /&gt;void *buffer = std::malloc(amount);&lt;br /&gt;world(writer_buffer(buffer, amount));&lt;/pre&gt;&lt;/blockquote&gt;Now an exception will be thrown if the callee tries to write more data than it should.&lt;br /&gt;&lt;br /&gt;&lt;h4 style="text-align: center;"&gt;std::function&lt;/h4&gt;Lastly, C++ 2011 added the ability for more verbose type checking on function objects, and the ability to create the save/write function as a normal function as opposed to a template function. That ability is a general reusable function object facade, &lt;a href="http://en.cppreference.com/w/cpp/utility/functional/function" target="_blank"&gt;std::function&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;To rewrite World to use it, we'd do as follows:  &lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;void world(std::function&amp;lt;void (const void *, size_t)&amp;gt; func)&lt;br /&gt;{&lt;br /&gt;  //Do some stuff...&lt;br /&gt;  //Do some more stuff...&lt;br /&gt;  func("World", 5); //Write 5 characters via callback&lt;br /&gt;  //Do some more stuff...&lt;br /&gt;  unsigned char *data = ...;&lt;br /&gt;  func(data, data_size); //Write some bytes&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;With &lt;i&gt;std::function&lt;/i&gt;, the type is now made explicit instead of being a template. It is anything which receives any kind of buffer and its length, and returns nothing. This can ensure that callers will always use a compatible function as intended by the library designer. For example, in our case, the caller only needs to ensure that data can be passed via a &lt;i&gt;char *&lt;/i&gt; and an &lt;i&gt;unsigned char *&lt;/i&gt;, based on how World uses the callback function. If World was now modified to also output an &lt;i&gt;int *&lt;/i&gt;, less capable callers would now break. std::function can ensure that things are designed properly up front. With &lt;i&gt;std::function&lt;/i&gt;, you can now also restructure your code to place various components in different compilation units if you so desire, although perhaps at a performance penalty.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;"&gt;Conclusion&lt;/h3&gt;To wrap up, you should now understand some features of C++ that are not as commonly used, or some new features of C++ 2011 that you may not be familiar with. You should now also have some ideas about generic code which should help you improve code you write.&lt;br /&gt;&lt;br /&gt;Many examples above were given only with one methodology, although they can be implemented with some of the others. For practice, try doing this yourself. Also try applying these ideas to other kinds of storage mechanisms not covered here, doing so should now be rather trivial for you.&lt;br /&gt;&lt;br /&gt;Remember, while this was done with a few standard examples and for writing, it can be extended to all handles Win32 offers, or for reading, or for anything else.</description><link>http://insanecoding.blogspot.com/2013/04/designing-c-functions-to-writesave-to.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>5</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-5607941569663788551</guid><pubDate>Tue, 19 Mar 2013 12:12:00 +0000</pubDate><atom:updated>2013-03-23T14:36:52.443-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>pure failure</category><category domain='http://www.blogger.com/atom/ns#'>crazy executives</category><category domain='http://www.blogger.com/atom/ns#'>compatibility</category><category domain='http://www.blogger.com/atom/ns#'>Library</category><category domain='http://www.blogger.com/atom/ns#'>torture</category><category domain='http://www.blogger.com/atom/ns#'>API</category><category domain='http://www.blogger.com/atom/ns#'>bad code</category><category domain='http://www.blogger.com/atom/ns#'>PHB</category><category domain='http://www.blogger.com/atom/ns#'>secure</category><category domain='http://www.blogger.com/atom/ns#'>standards compliance</category><category domain='http://www.blogger.com/atom/ns#'>Portability</category><category domain='http://www.blogger.com/atom/ns#'>protocols</category><title>OAuth - A great way to cripple your API</title><description>&lt;h3 style="text-align: center;"&gt;Intro &lt;/h3&gt;&amp;nbsp;A few years ago, the big social networking sites were looking for a secure way to allow their users to safely use any and all untrusted software to access their own personal accounts. So that a user could have their account on one social networking site safely interact with their account on another social networking site. They also wanted to allow for users to be able to allow their accounts to interact safely with various untrusted web applications and web sites.&lt;br /&gt;&lt;br /&gt;In order to safely allow untrusted software to access a user's account, a few points needed to be kept in mind. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Untrusted software should not have access to a user's credentials, in case the software is compromised, passwords will not be stolen, as user's passwords are not stored by the software.&lt;/li&gt;&lt;li&gt;Untrusted software should not have full access to a user's account, but only limited access as defined by the user. In the same vein, giving the software user's personal credentials will allow unlimited access to a user's account, which could be used maliciously.&lt;/li&gt;&lt;li&gt;A user should be able to revoke the permission they granted to allow particular untrusted software to work, in case they turn malicious, despite the limited access they have.&lt;/li&gt;&lt;/ul&gt;A solution that was developed for this use-case was created - &lt;a href="http://en.wikipedia.org/wiki/OAuth" target="_blank"&gt;OAuth&lt;/a&gt;. OAuth's primary use-case is the one described above.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;"&gt;Implementation &lt;/h3&gt;OAuth is generally implemented in a fashion where the untrusted software is accessed by a user via a standard web browser. In order for a user to authorize that software, the software will redirect the user's browser to a page on the social networking site, with a couple of parameters sent to it. Now that the user is on his social networking site, the untrusted software no longer has control over what the user is doing, as the user left the untrusted software, allowing the user to safely log in to his social networking account. Then, the social networking site will see the parameters it was passed, and ask the user if he or she wants to authorize the software in question, and what kind of access to the user's account it should be given.&lt;br /&gt;&lt;br /&gt;If and when the user has authorized the untrusted software, the social networking site can then report back to the untrusted software that it was granted a certain amount of access, and give it some credentials to use. These credentials are unique to the user and the software in question. The social networking site allows for a user to later on see a list of software authorized, and revoke the unique credentials given to any one of them, or modify the amount of access a particular set of credentials has. &lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;"&gt;Problems&lt;/h3&gt;&lt;h4 style="text-align: center;"&gt;There is no standard&lt;/h4&gt;Now above, I said OAuth is &lt;i&gt;generally&lt;/i&gt; implemented in this fashion. I say generally, because unlike standard HTTP authentication schemes (&lt;a href="http://en.wikipedia.org/wiki/Basic_access_authentication" target="_blank"&gt;Basic&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Digest_access_authentication" target="_blank"&gt;Digest&lt;/a&gt;, and others), OAuth is a big grab bag of ideas which can be mixed and matched in an infinite amount of ways, and also allows for developers to make their own unique tweaks to their personal implementations.&lt;br /&gt;&lt;br /&gt;With the standard HTTP authentication schemes, once a developer knows the protocol, and implemented it with one web site, that exact same knowledge can be reused to logging into any other web site that supports the standard. Likewise, software libraries can be made to handle HTTP authentication, and all a third party developer needs to do is specify to the library which credentials should be used, and then everything works as expected.&lt;br /&gt;&lt;br /&gt;With OAuth, once a developer learns how to authenticate with it to one web site, it is likely that the same developer will need to relearn how to connect to every other web site using OAuth. This further means that every web site which supports OAuth needs to document exactly how it is implementing it, and what tweaks are in use. It also means that no library can be written which can simply support every OAuth implementation out there. This places a great burden on developers on both sides. It can also greatly increase frustration for less able users, when their favorite library works great with one site they support, but are unable to extend their software to another site, because their library lacks some aspect of OAuth for this new site, or a unique OAuth tweak on this new site renders the library incompatible.&lt;br /&gt;&lt;br /&gt;Here are some choice quotes from the &lt;a href="http://tools.ietf.org/html/rfc6749#section-1.8" target="_blank"&gt;official RFC&lt;/a&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;However, as a rich and highly extensible framework with many optional components, on its own, this specification is likely to produce a wide range of &lt;u&gt;non-interoperable&lt;/u&gt; implementations.&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;This framework was designed with the clear expectation that &lt;u&gt;future work&lt;/u&gt; will define prescriptive profiles and extensions necessary to achieve full web-scale interoperability.&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Another issue is that while various standard HTTP authentication schemes have well understood security margins, OAuth is entirely variable. On one web site, its OAuth implementation may be secure, while on another, &lt;a href="http://www.thread-safe.com/2012/01/problem-with-oauth-for-authentication.html" target="_blank"&gt;its implementation may be Swiss cheese&lt;/a&gt;. Even though a security consultant should generally look over any authorization implementation to ensure mistakes were not made, laymen can have a good understanding how reliable and secure their standardized authentication scheme is. A manager can ask their developers if some bullet points were adhered to, and then be reasonably confident in their security. Whereas with OAuth, the entire (complex) implementation needs to be reviewed from top to bottom by a top security professional to ensure it is secure. A manager has no adequate set of bullet points to discuss with their developers, as unique implementation details will drastically change the applicability of various points, with many important details still missing. At best, a manager can only get a false sense of security when OAuth is in use. The designers of OAuth respond to this point with a &lt;b&gt;71 page document&lt;/b&gt; of &lt;a href="http://tools.ietf.org/html/rfc6819" target="_blank"&gt;security issues&lt;/a&gt; that need to be dealt with!&lt;br /&gt;&lt;br /&gt;What all this boils down to, is that OAuth is really just a set of ideas and recommendations on how to implement a unique authorization scheme. OAuth does not allow for interoperability as standards (usually) guarantee. Essentially, OAuth ensures that API authentication with your web site will be confusing, and will only work for the exact use-case for social networking sites described above.&lt;br /&gt;&lt;br /&gt;&lt;h4 style="text-align: center;"&gt;Crippling Design - APUI&lt;/h4&gt;The common OAuth use-case described above is to allow for a user on one web site to allow their software to communicate for them with another web site. The workflow described above requires that a user navigate between web sites using their browser and manually enter their credentials and authorization to various aspects of their account as part of the overall software authorization process.&lt;br /&gt;&lt;br /&gt;This means that OAuth (at least how it's normally implemented) only works between two web sites, with individual users, and that user intervention is required in order for software to authenticate with another web site. The fact that user intervention is required with manual input means that any API behind OAuth is not an &lt;i&gt;API&lt;/i&gt; - Application Programming Interface, but an &lt;b&gt;&lt;i&gt;AP&lt;u&gt;U&lt;/u&gt;I&lt;/i&gt;&lt;/b&gt; - &lt;u&gt;Application Programming &lt;b&gt;User&lt;/b&gt; Interface&lt;/u&gt;, meaning user intervention is required for functionality. All in all, this cripples your API, or APUI as it should now properly be called.&lt;br /&gt;&lt;br /&gt;Let us now focus on what cannot be properly done with OAuth in place:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Third party software which is not part of a web site cannot interact with an OAuth &lt;i&gt;APUI&lt;/i&gt;.&lt;/li&gt;&lt;li&gt;One user in third party software cannot act on behalf of another user via an OAuth &lt;i&gt;APUI&lt;/i&gt;.&lt;/li&gt;&lt;li&gt;Third party software cannot run automated processes on an OAuth &lt;i&gt;APUI&lt;/i&gt;.&lt;/li&gt;&lt;li&gt;Organizations cannot ensure tight integration between various software and services they use.&lt;/li&gt;&lt;/ul&gt;Let us review an example case where a company launches a new online service for coordinating schedules and personal calendars between people. We'll call this new online service &lt;i&gt;Calendar&lt;/i&gt;. The developers of Calendar create an &lt;i&gt;APUI&lt;/i&gt; for it using OAuth, so third party software can integrate with Calendar.&lt;br /&gt;&lt;br /&gt;As described above, a user needs to navigate between one web site and another in order to authorize software, with the two web sites sending each other information. What if one wants to integrate something which isn't a web site with Calendar? There's tons of desktop calendaring applications, Microsoft Outlook, Mozilla Lightning, Evolution, KOrganizer, Kontact, and more. If their developers want to integrate with the Calendar service, they need to embed a web browser in their applications now?&lt;br /&gt;&lt;br /&gt;Furthermore, that may not even help, if the OAuth workflow requires information be sent to an existing web site, what web site is associated with a user's personal copy of software? Developers of that software are unlikely to create a web site with user accounts just for this integration. Even if they did, if the site goes down (temporarily), then the integration stops working. Even though, in theory, there should be no dependance of some extra web site between Calendar and the software trying to integrate with it.&lt;br /&gt;&lt;br /&gt;&lt;h4 style="text-align: center;"&gt;Insecure &lt;/h4&gt;Also, as a security consideration, if an application does embed a web browser in it so it can authenticate with OAuth, the first requirement is no longer met - &lt;i&gt;Untrusted software should not have access to a user's credentials&lt;/i&gt;. When using a standard web browser, once a user leaves the third party software's site and redirects to Calendar's site, the third party software cannot steal the information the user is entering. But when the third party software itself is the one which browses to Calendar's site, then it has access to everything the user is entering, including passwords.&lt;br /&gt;&lt;br /&gt;Actually, this attack works on OAuth in every circumstance, including web site to web site, and I've actually used it in practice. A web site can embed a web browser via a Java Applet or similar, or have a web browser server side which presents the OAuth log in page to the user, but slightly modified to have all the data entered pass through the third party site. Therefore OAuth doesn't even fulfill its own primary security objective!&lt;br /&gt;&lt;br /&gt;&lt;h4 style="text-align: center;"&gt;Incompatible with Enterprise&lt;/h4&gt;Next, once we go to the enterprise level, OAuth starts becoming much worse. Say a boss has his secretary manage his calendar for him, which is a very common scenario. In many OAuth setups, he cannot enter his Calendar credentials into the company-wide calendaring software running on a secure company server, which the secretary can then access. Rather, he would need to enter it directly in the browser the secretary uses, and stay there checking off many options. Also it is common that OAuth implementations are using security tokens which &lt;i&gt;expire&lt;/i&gt;, meaning the boss will need to keep reentering his Calendar credentials again and again. Most bosses will just get fed up and give his secretary his credentials, especially if he's not physically near his secretary. It is also likely that the secretary will then write the password down. This gets compounded if multiple secretaries manage his schedule.&lt;br /&gt;&lt;br /&gt;Now say an organization has software for which it would like to run background processes for all its users with Calendar. Perhaps every week it would like to automatically analyze the Calendar accounts of all department chiefs to find a good time for a weekly meeting. How would this work exactly? Every department chief would now have to go and enter their credentials into this software? Then do it again each time security tokens expire from past authentications?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Of course this is only the beginning. Since OAuth was designed for the likes of Twitter and Facebook which cater to individual personal accounts, the common implementations do not allow for hierarchical permissions as enterprise organizations need.&lt;br /&gt;&lt;br /&gt;In enterprise infrastructure, software is already used which has well defined roles and access rights for ever single user. This infrastructure should be deciding who can do what, and to what level one user can act on behalf of another user. Once an organization purchases accounts for all their employees from Calendar, no employee should be able to turn off or limit what the enterprise management software can do with their Calendar account. The enterprise management software is the one who needs to make such decisions. This flies in the face of &lt;i&gt;Untrusted software should not have full access to a user's account, but only limited access as defined by the user&lt;/i&gt; and &lt;i&gt;A user should be able to revoke the permission they granted to allow particular untrusted software to work&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;The amount of work involved to tightly integrate Calendar with existing infrastructure is also enormous from a user perspective. Every single account now has to have a user navigate across web pages and check all kinds of boxes until all the users are integrated. OAuth implementations generally forget to have administrator accounts which can do everything on behalf of other users in their organization.&lt;br /&gt;&lt;br /&gt;It should be obvious at this point whether enterprise organizations  would be willing to purchase accounts for their entire staff with  Calendar, when integration into their existing infrastructure or new  endeavors with the service will be difficult if not outright impossible.  Imagine how much money Calendar sales now stand to lose from being  unattractive to enterprise clients.&lt;br /&gt;&lt;br /&gt;&lt;h4 style="text-align: center;"&gt;Repel third party developers &lt;/h4&gt;OAuth implementations also generally require that any software which uses their &lt;i&gt;APUI&lt;/i&gt;s be preregistered in advance. This places extra burden on third party developers. The OAuth implementations also commonly require that the third party web site integrating be preregistered in advance, so you can say goodbye to your application being compatible with staging servers which may be at another URL. It also makes software much less attractive when one party sells software to another party, as every new client now needs to go through an application registration process for the URLs they plan to setup the software they are purchasing. Therefore third party developers are less likely to be interested in selling software which integrates with Calendar, as there's hassle involved with every single sale.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;"&gt;Recap &lt;/h3&gt;&lt;ul&gt;&lt;li&gt;OAuth is not a standard, but a set of ideas, which does not allow third party developers to reuse knowledge, and places extra documentation burden on implementers.&lt;/li&gt;&lt;li&gt;OAuth as a whole has undefined security characteristics.&lt;/li&gt;&lt;li&gt;OAuth doesn't properly fulfill its primary security objectives.&lt;/li&gt;&lt;li&gt;OAuth doesn't work well outside social networking web site use-cases.&lt;/li&gt;&lt;li&gt;OAuth services are unattractive to enterprise organizations looking to integrate such services into their infrastructure.&lt;/li&gt;&lt;li&gt;OAuth services are less likely to have professional third parties sell software based upon them.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;"&gt;Solutions&lt;/h3&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-nXwWoEBjKJg/UUg4VUOI83I/AAAAAAAAAJE/_yJpyAclQGQ/s1600/no-oauth.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-nXwWoEBjKJg/UUg4VUOI83I/AAAAAAAAAJE/_yJpyAclQGQ/s1600/no-oauth.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;If you're looking to implement authorization for your API, I recommend to sticking with well understood secure designs, such as HTTP Basic Authentication over SSL/TLS (or HTTP Digest Authentication).&lt;br /&gt;&lt;br /&gt;In order to achieve a situation where users can securely authorize third party software, without giving over their personal credentials (passwords), I recommend that these services have a page where they can generate new credentials (keys) which the user can copy and paste. They can then name these keys themselves (avoiding application registration hassle), and set permissions upon them themselves. Since the user is the one initiating the key creation, and copying and pasting it themselves, they cannot fall prey to a &lt;a href="http://insanecoding.blogspot.com/2009/11/malicious-hackers-are-not-out-there.html" target="_blank"&gt;man-in-the-middle attack&lt;/a&gt; where the third party software initiates the authorization process.&lt;br /&gt;&lt;br /&gt;But remember the use-cases described here, and ensure that organizations have a way to access all user accounts company-wide, and without individual users being able to disable or limit that access.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="text-align: center;"&gt;Conclusion&lt;/h3&gt;&lt;br /&gt;If you want your service to be used by everyone out there, be well supported by third parties, and to have them create all kinds of interesting software with it, &lt;u&gt;do &lt;b&gt;not&lt;/b&gt; use OAuth&lt;/u&gt;.&lt;br /&gt;&lt;br /&gt;Even the original social networking sites behind OAuth decided they really need other options for different use-cases, such as &lt;a href="https://dev.twitter.com/docs/oauth/xauth" target="_blank"&gt;Twitter's xAuth,&lt;/a&gt; or Yahoo offering &lt;a href="http://developer.yahoo.com/messenger/guide/chapterdirectoauth.html" target="_blank"&gt;&lt;i&gt;Direct OAuth&lt;/i&gt;&lt;/a&gt;, which turns the entire scheme into a more complicated version of HTTP Basic Authentication, with no added benefits. Perhaps the most damaging point against OAuth, is that the original designer behind it decided to &lt;a href="http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/" target="_blank"&gt;remove his name from the specification, and is washing his hands clean of it&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I find it really amazing at how blind many big players are these days to all the problems with OAuth. When I first heard that IBM, a major enterprise player started offering services only accessible with typical utterly crippled OAuth, I was overcome with disbelief. Yet at the same time, I hear that they're &lt;i&gt;wondering&lt;/i&gt; why they're not seeing the sales they used to with other services they offer, or compared to the competition.&lt;br /&gt;&lt;br /&gt;I'm even more amazed to see other big companies throwing away their currently working authentication systems for OAuth. Followed by them &lt;i&gt;wondering&lt;/i&gt; why many third party developers are not upgrading to support the new authentication scheme, and clients jumping ship to inferior services.&lt;br /&gt;&lt;br /&gt;It seems many developers and managers out there simply &lt;i&gt;don't get it&lt;/i&gt;. If you know anyone like that, show them this article.</description><link>http://insanecoding.blogspot.com/2013/03/oauth-great-way-to-cripple-your-api.html</link><author>noreply@blogger.com (insane coder)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-nXwWoEBjKJg/UUg4VUOI83I/AAAAAAAAAJE/_yJpyAclQGQ/s72-c/no-oauth.png' height='72' width='72'/><thr:total>24</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-168693071028164266</guid><pubDate>Sun, 02 Dec 2012 01:02:00 +0000</pubDate><atom:updated>2012-12-01T17:09:08.665-08:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>x86-64</category><category domain='http://www.blogger.com/atom/ns#'>pure failure</category><category domain='http://www.blogger.com/atom/ns#'>x86</category><category domain='http://www.blogger.com/atom/ns#'>torture</category><category domain='http://www.blogger.com/atom/ns#'>debian</category><category domain='http://www.blogger.com/atom/ns#'>bad code</category><category domain='http://www.blogger.com/atom/ns#'>OSS</category><title>Debian breaks OSS4</title><description>&lt;p&gt;Several people have contacted me to tell me that the latest version of OSS4 in Debian Unstable &lt;i&gt;&lt;a href="http://packages.debian.org/changelogs/pool/main/o/oss4/current/changelog" target="_blank"&gt;4.2-build2007-1+nmu1&lt;/a&gt;&lt;/i&gt; introduces several audio issues such as garbled sound or kernel panics. I can confirm I have issues as well with this version.&lt;/p&gt;&lt;p&gt;Downgrading to &lt;i&gt;4.2-build2007-1&lt;/i&gt; fixes the problem.&lt;/p&gt;&lt;p&gt;I recommending putting the following in &lt;i&gt;/etc/apt/preferences&lt;/i&gt;:&lt;br/&gt;&lt;blockquote&gt;Package: oss4-base oss4-dev oss4-dkms oss4-gtk&lt;br /&gt;Pin: version 4.2-build2007-1+nmu1&lt;br /&gt;Pin-Priority: -1&lt;/blockquote&gt;This will prevent Debian from trying to upgrade to that version. &lt;/p&gt;&lt;p&gt;If you already accidentally upgraded to it, older versions are still &lt;a href="http://snapshot.debian.org/package/oss4/4.2-build2007-1/"&gt;available&lt;/a&gt;.&lt;/p&gt;</description><link>http://insanecoding.blogspot.com/2012/12/debian-breaks-oss4.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-2453563882105686273</guid><pubDate>Thu, 19 Jul 2012 13:06:00 +0000</pubDate><atom:updated>2012-07-23T07:46:56.132-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>x86-64</category><category domain='http://www.blogger.com/atom/ns#'>Function Pointers</category><category domain='http://www.blogger.com/atom/ns#'>Library</category><category domain='http://www.blogger.com/atom/ns#'>debian</category><category domain='http://www.blogger.com/atom/ns#'>GCC</category><category domain='http://www.blogger.com/atom/ns#'>insane ideas</category><category domain='http://www.blogger.com/atom/ns#'>closed source</category><category domain='http://www.blogger.com/atom/ns#'>open source</category><category domain='http://www.blogger.com/atom/ns#'>good code</category><category domain='http://www.blogger.com/atom/ns#'>compatibility</category><category domain='http://www.blogger.com/atom/ns#'>x86</category><category domain='http://www.blogger.com/atom/ns#'>API</category><category domain='http://www.blogger.com/atom/ns#'>binary</category><category domain='http://www.blogger.com/atom/ns#'>c99</category><category domain='http://www.blogger.com/atom/ns#'>standards compliance</category><category domain='http://www.blogger.com/atom/ns#'>Portability</category><title>Creating portable Linux binaries</title><description>For some, the idea of creating a portable Linux binary is somewhat elusive.&lt;br /&gt;&lt;br /&gt;In this article, we will be discussing how to create a Linux binary for a specific architecture, that you will have great success running on a large variety of Linux distros. This includes current releases, somewhat old ones, and hopefully far into the future.&lt;br /&gt;&lt;br /&gt;A common problem facing those looking to deploy proprietary software on Linux, or for those trying to supply binaries to a very large user-base which will not compile your software themselves, is how to offer one binary that fits most normal scenarios.&lt;br /&gt;&lt;br /&gt;There are generally four naive approaches to solving this problem.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The developers set up a bunch of specific distros, and compile the software on each of them, and give out distro specific binaries. This makes sense at first, till you run into some trouble. &lt;ul&gt;&lt;li&gt;You have to juggle many live CDs or maintain a bunch of installed distros which is painful and time consuming.&lt;/li&gt;&lt;li&gt;You end up only offering support for the distros you have handy, and you will get quite a few users on a more exotic distro nagging you for support, or a different and incompatible version of a distro you're already supporting.&lt;/li&gt;&lt;li&gt;The compilers or other build utilities on some distros are too old for your modern software, and you need to build them elsewhere, or figure out how to back port modern software to that old distro.&lt;/li&gt;&lt;li&gt;Builds break when a user upgrades their system.&lt;/li&gt;&lt;li&gt;Users end up needing to install some non standard system libraries, increasing everyone's frustration.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;The developers just statically link the binaries. This isn't always a legal option due to some licenses that may be involved. Binaries which are fully statically linked also in many instances exhibit incorrect behavior (more on this later). &lt;/li&gt;&lt;li&gt;The developers just compile the software on one system, and pray that it works for everyone else.&lt;/li&gt;&lt;li&gt;Compile with a really really old distro and hope it works everywhere else. However this succumbs to the last three problems outlined in naive approach #1, and in many cases the binaries produced won't work with modern distros.&lt;/li&gt;&lt;/ol&gt;Now there are plenty of companies that supply those portable Linux binaries. You find on their website downloads for say Linux i386, AMD64, and PPC. Somehow that i386 binary manages to run on every i386 system you've tested, Red Hat, Debian, SUSE, Ubuntu, Gentoo, and both old and modern versions at that. What is their secret sauce?&lt;br /&gt;&lt;br /&gt;Now let us dive into all the important information and techniques to accomplish this worthy goal.&lt;br /&gt;&lt;br /&gt;First thing you want to know is what exactly is your binary linked to anyway? For this, the handy &lt;i&gt;ldd&lt;/i&gt; command comes in.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;/tmp&amp;gt; ldd myapp&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; linux-vdso.so.1 =&amp;gt;&amp;nbsp; (0x00007fff7a1ff000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libstdc++.so.6 =&amp;gt; /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1f8a765000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1f8a4e3000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libgcc_s.so.1 =&amp;gt; /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1f8a2cc000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1f89f45000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /lib64/ld-linux-x86-64.so.2 (0x00007f1f8aaa9000)&lt;br /&gt;/tmp&amp;gt; &lt;/blockquote&gt;The lines which are directed to a file are system libraries that you need to worry about. In this case, there's libstdc++, libm, libgcc, and libc. libc and libm are both part of (&lt;a href="http://www.eglibc.org/home" target="_blank"&gt;E&lt;/a&gt;)&lt;a href="http://www.gnu.org/software/libc/" target="_blank"&gt;GLIBC&lt;/a&gt;, the C library that most Linux applications will be using. &lt;a href="http://gcc.gnu.org/libstdc++/" target="_blank"&gt;libstdc++&lt;/a&gt; is &lt;a href="http://gcc.gnu.org/" target="_blank"&gt;GCC&lt;/a&gt;'s C++ library. &lt;a href="http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html" target="_blank"&gt;libgcc&lt;/a&gt; is GCC's implementation of some programming constructs that your program may be using, such as exception handling, and things like that.&lt;br /&gt;&lt;br /&gt;In general (E)GLIBC is broken up into many sub libraries that your program may be linked against. Other notable examples are libdl for Dynamic Loading, libpthread for threading, librt for various real time functions, and a few others.&lt;br /&gt;&lt;br /&gt;Your application will not run on a system unless all these dependencies are found, and are compatible. Therefore, versions of these also come into play. In general a newer minor version of a library will work, but not an older.&lt;br /&gt;&lt;br /&gt;In order to find versions numbers, you want to use &lt;i&gt;objdump&lt;/i&gt;. Here's an example with finding out what version of (E)GLIBC is needed:&lt;br /&gt;&lt;blockquote&gt;/tmp&amp;gt; objdump -T myapp | grep GLIBC_&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 ungetc&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.3&amp;nbsp;&amp;nbsp; __ctype_toupper_loc&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fputc&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 free&lt;br /&gt;…&lt;br /&gt;/tmp&amp;gt;&lt;/blockquote&gt;In this case, 2.3 is the highest version number. Therefore this binary needs (E)GLIBC 2.3 or higher on the system. Note, the version numbers have nothing to do with the version installed on your system, rather (E)GLIBC marks each function with the minimum version that contains it.&lt;br /&gt;&lt;br /&gt;Of course all this applies to other libraries as well, particularly libgcc and libstdc++.&lt;br /&gt;&lt;br /&gt;Now that we know a little bit about what we're doing, I'm going to present the first bit of secret sauce.&lt;br /&gt;&lt;br /&gt;If you're using C++, link with &lt;i&gt;-static-libstdc++&lt;/i&gt; this will ensure that libstdc++ is linked statically, but won't link every other lib statically like &lt;i&gt;-static&lt;/i&gt; would. You want libstdc++ linked statically, because it's safe to do so, some systems may be using an older version (or have none at all, in the case of some servers), or you want your binary to remain compatible if a new major version of libstdc++ comes out which is no longer backwards compatible. Note that even though libstdc++ is GPL'd, it also offers a &lt;a href="http://gcc.gnu.org/onlinedocs/libstdc++/manual/license.html" target="_blank"&gt;linking exception&lt;/a&gt; that allows you to link against it and even statically link it in any application.&lt;br /&gt;&lt;br /&gt;If you see that your binary needs libgcc, also use &lt;i&gt;-static-libgcc&lt;/i&gt; for the same reasons given above. Also, GCC is GPL'd, and has the same &lt;a href="http://www.gnu.org/licenses/gcc-exception.html" target="_blank"&gt;linking exception&lt;/a&gt; as above. I once had the unfortunate scenario where I sold a client an application without libgcc statically linked, that used exceptions. On his old server, as long as everything went absolutely perfectly, the application ran fine, but if any issue occurred, instead of gracefully handling the issue, the application terminated immediately. Since his libgcc was too old, the application saw the throws, but none of the catches. Statically linking libgcc fixed this issue.&lt;br /&gt;&lt;br /&gt;Now you might be thinking, hey what about statically linking (E)GLIBC? Let me warn you that doing so is a bad idea. Some features in (E)GLIBC will only work if the statically linked (E)GLIBC is the exact same version of (E)GLIBC installed on the system, making statically linking pointless, if not downright problematic. (E)GLIBC's libdl is quite notable in this regard, as well as several networking functions. (E)GLIBC is also licensed under &lt;a href="http://www.gnu.org/software/libc/manual/html_node/Copying.html#Copying" target="_blank"&gt;LGPL&lt;/a&gt;. Which essentially means that if you give out the source to your application, then in most cases you can distribute statically linked binaries with it, but otherwise, not. Also, since 99% of the functions are marked as requiring extremely old versions of (E)GLIBC, statically linking is hardly necessary in most cases.&lt;br /&gt;&lt;br /&gt;The next bit of the secret sauce is statically linking those non standard libs your application needs but nothing else.&lt;br /&gt;&lt;br /&gt;You probably never learned in school how to selectively static link those libraries you want, but it is indeed possible. Before the list of libraries you wish to static link, place &lt;i&gt;-Wl,-Bstatic&lt;/i&gt; and afterwards &lt;i&gt;-Wl,-Bdynamic&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Say in my application I want to statically link &lt;a href="http://curl.haxx.se/" target="_blank"&gt;libcurl&lt;/a&gt; and &lt;a href="http://www.openssl.org/" target="_blank"&gt;OpenSSL&lt;/a&gt;, but want to dynamically link &lt;a href="http://zlib.net/" target="_blank"&gt;zlib&lt;/a&gt;, and the rest of my libs, such as other parts of (E)GLIBC, I would use the following as my link flags:&lt;br /&gt;&lt;i&gt;gcc -o app *.o &lt;u&gt;-static-libgcc -Wl,-Bstatic -lcurl -lssl -lcrypto -Wl,-Bdynamic&lt;/u&gt; -lz -ldl -lpthread -lrt &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The next step is to ensure that your libraries pull in as few dependencies as possible. Here's the output from &lt;i&gt;ldd&lt;/i&gt; on my libcurl.so:&lt;br /&gt;&lt;blockquote&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; linux-vdso.so.1 =&amp;gt;&amp;nbsp; (0x00007fffbadff000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libidn.so.11 =&amp;gt; /usr/lib/x86_64-linux-gnu/libidn.so.11 (0x00007f84410a4000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libssh2.so.1 =&amp;gt; /usr/lib/x86_64-linux-gnu/libssh2.so.1 (0x00007f8440e7b000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; liblber-2.4.so.2 =&amp;gt; /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2 (0x00007f8440c6b000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libldap_r-2.4.so.2 =&amp;gt; /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2 (0x00007f8440a1a000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; librt.so.1 =&amp;gt; /lib/x86_64-linux-gnu/librt.so.1 (0x00007f8440812000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libgssapi_krb5.so.2 =&amp;gt; /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007f84405d2000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libssl.so.1.0.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007f8440374000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libcrypto.so.1.0.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f843ff90000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; librtmp.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/librtmp.so.0 (0x00007f843fd75000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libz.so.1 =&amp;gt; /lib/x86_64-linux-gnu/libz.so.1 (0x00007f843fb5e000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007f843f7d7000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libgcrypt.so.11 =&amp;gt; /lib/x86_64-linux-gnu/libgcrypt.so.11 (0x00007f843f558000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libresolv.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f843f342000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libsasl2.so.2 =&amp;gt; /usr/lib/x86_64-linux-gnu/libsasl2.so.2 (0x00007f843f127000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libgnutls.so.26 =&amp;gt; /usr/lib/x86_64-linux-gnu/libgnutls.so.26 (0x00007f843ee66000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f843ec4a000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /lib64/ld-linux-x86-64.so.2 (0x00007f844157e000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libkrb5.so.3 =&amp;gt; /usr/lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007f843e976000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libk5crypto.so.3 =&amp;gt; /usr/lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007f843e74c000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libcom_err.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007f843e548000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libkrb5support.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007f843e33f000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f843e13a000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libkeyutils.so.1 =&amp;gt; /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007f843df36000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libgpg-error.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f843dd32000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libtasn1.so.3 =&amp;gt; /usr/lib/x86_64-linux-gnu/libtasn1.so.3 (0x00007f843db21000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libp11-kit.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libp11-kit.so.0 (0x00007f843d90f000)&lt;/blockquote&gt;This is quite unacceptable. Distros generally compile packages with everything enabled. Your application generally does not need everything a library has to offer. In the case of libcurl, you can compile it yourself, and disable the features you aren't using. In an example application, I only need HTTP and FTP support, so I could compile libcurl with very little, and now have this:&lt;br /&gt;&lt;blockquote&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; linux-vdso.so.1 =&amp;gt;&amp;nbsp; (0x00007fffbadff000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; librt.so.1 =&amp;gt; /lib/x86_64-linux-gnu/librt.so.1 (0x00007f8440812000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libssl.so.1.0.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007f8440374000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libcrypto.so.1.0.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f843ff90000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libz.so.1 =&amp;gt; /lib/x86_64-linux-gnu/libz.so.1 (0x00007f843fb5e000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007f843f7d7000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libresolv.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f843f342000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f843ec4a000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /lib64/ld-linux-x86-64.so.2 (0x00007f844157e000)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f843e13a000) &lt;/blockquote&gt;This is much more manageable. Refer to the documentation of your libraries in order to see how to compile them without&amp;nbsp; features you don't need.&lt;br /&gt;&lt;br /&gt;If you're going to be compiling your own libraries, you probably want to set up a second system, virtual machine, or a &lt;a href="http://en.wikipedia.org/wiki/Chroot" target="_blank"&gt;chroot&lt;/a&gt; for building your customized library versions and applications, to ensure it doesn't conflict with your main system. Especially for the upcoming tip.&lt;br /&gt;&lt;br /&gt;Secret sauce part 3, push your (E)GLIBC requirements down.&lt;br /&gt;&lt;br /&gt;Let's look at an &lt;i&gt;objdump&lt;/i&gt; on OpenSSL.&lt;br /&gt;&lt;blockquote&gt;/tmp&amp;gt; objdump -T /usr/lib/libcrypto.so.0.9.8 | grep GLIBC_&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 chmod&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fileno&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 __sysv_signal&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 printf&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 memset&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 ftell&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 getgid&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 shutdown&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 close&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 syslog&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 ioctl&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 abort&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 memchr&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 gethostbyname&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fseek&lt;br /&gt;&lt;b&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.7&amp;nbsp;&amp;nbsp; __isoc99_sscanf&lt;/b&gt;&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 openlog&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 exit&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strcasecmp&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 gettimeofday&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 setvbuf&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 read&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strncmp&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 malloc&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fopen&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 setsockopt&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 sysconf&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 getpid&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fgets&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 geteuid&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 vfprintf&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 closelog&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fputc&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 times&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 free&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strlen&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 ferror&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 opendir&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 __xstat&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 listen&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.3&amp;nbsp;&amp;nbsp; __ctype_b_loc&lt;br /&gt;0000000000000000&amp;nbsp; w&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 __cxa_finalize&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 readdir&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 dlerror&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 sprintf&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DO *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 stdin&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strrchr&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 dlclose&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 poll&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 getegid&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 gmtime_r&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strerror&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 sigaction&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strcat&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 getsockopt&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fputs&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 lseek&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strtol&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 getsockname&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 connect&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 memcpy&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 memmove&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strchr&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 socket&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fread&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 __fxstat&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 getenv&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 __errno_location&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 qsort&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strncasecmp&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strcmp&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strcpy&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 getuid&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.3&amp;nbsp;&amp;nbsp; __ctype_tolower_loc&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 memcmp&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 feof&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fclose&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 dlopen&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 recvfrom&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strncpy&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 dlsym&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 closedir&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DO *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 stderr&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fopen64&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 sendto&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 bind&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fwrite&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 realloc&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 perror&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fprintf&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 localtime&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 write&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 accept&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 strtoul&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 open&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 time&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 fflush&lt;br /&gt;0000000000000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DF *UND*&amp;nbsp; 0000000000000000&amp;nbsp; GLIBC_2.2.5 getservbyname&lt;br /&gt;/tmp&amp;gt;&lt;/blockquote&gt;It seems that OpenSSL would work on (E)GLIBC 2.3, except for one pesky function which needs 2.7+. This is a problem if I want to ship an application with this modern OpenSSL on say Red Hat Enterprise Linux 5 which comes with GLIBC 2.5, or say Debian Stable from ~4 years ago, which only has 2.4.&lt;br /&gt;&lt;br /&gt;In this case OpenSSL is using a C99 version of sscanf(), but not actually by choice.&lt;br /&gt;&lt;br /&gt;In &lt;i&gt;/usr/include/stdio.h&lt;/i&gt; on (E)GLIBC 2.7+, you'll notice two blocks:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: green;"&gt;#if defined __USE_ISOC99 &amp;amp;&amp;amp; !defined __USE_GNU \&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;    &amp;amp;&amp;amp; (!defined __LDBL_COMPAT || !defined __REDIRECT) \&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;    &amp;amp;&amp;amp; (defined __STRICT_ANSI__ || defined __USE_XOPEN2K)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;# ifdef __REDIRECT&lt;/span&gt;&lt;br /&gt;&lt;span style="color: grey; font-style: italic;"&gt;/* For strict ISO C99 or POSIX compliance disallow %as, %aS and %a[&lt;/span&gt;&lt;br /&gt;&lt;span style="color: grey; font-style: italic;"&gt;   GNU extension which conflicts with valid %a followed by letter&lt;/span&gt;&lt;br /&gt;&lt;span style="color: grey; font-style: italic;"&gt;   s, S or [.  */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __REDIRECT (fscanf, (FILE *__restrict __stream,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;        __const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format, ...),&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;           __isoc99_fscanf) __wur;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __REDIRECT (scanf, (__const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format, ...),&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;           __isoc99_scanf) __wur;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __REDIRECT_NTH (sscanf, (__const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __s,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;            __const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format, ...),&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;         __isoc99_sscanf);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;# else&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __isoc99_fscanf (FILE *__restrict __stream,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;          __const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format, ...) __wur;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __isoc99_scanf (__const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format, ...) __wur;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __isoc99_sscanf (__const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __s,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;          __const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format, ...) __THROW;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#  define fscanf __isoc99_fscanf&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#  define scanf __isoc99_scanf&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#  define sscanf __isoc99_sscanf&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;# endif&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#endif&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;And&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: green;"&gt;# if !defined __USE_GNU \&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;     &amp;amp;&amp;amp; (!defined __LDBL_COMPAT || !defined __REDIRECT) \&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;     &amp;amp;&amp;amp; (defined __STRICT_ANSI__ || defined __USE_XOPEN2K)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#  ifdef __REDIRECT&lt;/span&gt;&lt;br /&gt;&lt;span style="color: grey; font-style: italic;"&gt;/* For strict ISO C99 or POSIX compliance disallow %as, %aS and %a[&lt;/span&gt;&lt;br /&gt;&lt;span style="color: grey; font-style: italic;"&gt;   GNU extension which conflicts with valid %a followed by letter&lt;/span&gt;&lt;br /&gt;&lt;span style="color: grey; font-style: italic;"&gt;   s, S or [.  */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __REDIRECT (vfscanf,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;           (FILE *__restrict __s,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      __const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format, _G_va_list __arg),&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;           __isoc99_vfscanf)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;     __attribute__ ((__format__ (__scanf__, &lt;/span&gt;&lt;span style="color: blue;"&gt;2&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;))) __wur;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __REDIRECT (vscanf, (__const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;        _G_va_list __arg), __isoc99_vscanf)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;     __attribute__ ((__format__ (__scanf__, &lt;/span&gt;&lt;span style="color: blue;"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;))) __wur;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __REDIRECT_NTH (vsscanf,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;         (__const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __s,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;          __const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;          _G_va_list __arg), __isoc99_vsscanf)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;     __attribute__ ((__format__ (__scanf__, &lt;/span&gt;&lt;span style="color: blue;"&gt;2&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;)));&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#  else&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __isoc99_vfscanf (FILE *__restrict __s,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;           __const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;           _G_va_list __arg) __wur;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __isoc99_vscanf (__const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;          _G_va_list __arg) __wur;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;extern&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; __isoc99_vsscanf (__const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __s,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;           __const &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *__restrict __format,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;           _G_va_list __arg) __THROW;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#   define vfscanf __isoc99_vfscanf&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#   define vscanf __isoc99_vscanf&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#   define vsscanf __isoc99_vsscanf&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#  endif&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;# endif&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;These two blocks of code make fscanf(), scanf(), sscanf(), vfscanf(), vscanf(), and vsscanf() use special C99 versions. Since older applications were already compiled against C89 versions, (E)GLIBC doesn't want to potentially break them and change how an existing function works. So instead, a new set of functions were created which only exist in (E)GLIBC 2.7+, and (E)GLIBC by default will direct all calls to these functions to the proper C99 versions when compiling.&lt;br /&gt;&lt;br /&gt;Now there are some defines you can set in your library code and application code to ensure it uses the old more backwards compatible versions, but getting the exact right combination of defines without breaking anything else can be tricky. It may also be tedious to modify a code-base you're not familiar with.&lt;br /&gt;&lt;br /&gt;Therefore, I recommend just deleting these two blocks from your &lt;i&gt;&amp;lt;stdio.h&amp;gt;&lt;/i&gt; on your build system. You want your build system to be able to build everything for backwards compatibility, right?&lt;br /&gt;&lt;br /&gt;If you're recompiling libraries like OpenSSL which are designed for massive portability with all kinds of systems, odds are, they're not looking for C99 support in basic scanf() family functions anyway. If you do happen to need C99 scanf() support in your application, I recommend that you add it manually with a specialized lib, for maximum portability. You can easily &lt;a href="http://daniel.haxx.se/projects/trio/" target="_blank"&gt;find a bunch online&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The last scenario that you may encounter is that you happen to want to use a modern library function. For most libs you can just statically link them, but that won't work for (E)GLIBC. Since some functions depend on system support, or that custom versions don't perform as well as the built in system ones, you definitely want to use the built in ones if they're available. The question is, how to once the binary has already been compiled?&lt;br /&gt;&lt;br /&gt;So for our final bit of secret sauce, dynamically load any modern functions that you want to use, and work around them, or disable some functionality if not present.&lt;br /&gt;&lt;br /&gt;Remember libdl that we mentioned above? It offers &lt;a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/dlopen.html" target="_blank"&gt;dlopen()&lt;/a&gt; for opening system libraries, and &lt;a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html" target="_blank"&gt;dlsym()&lt;/a&gt; for finding out if certain functions are present or not, and retrieving a pointer to them.&lt;br /&gt;&lt;br /&gt;I'm going to post a full example that you can look at and play with. In this example, we have a program which tries to figure out how big system &lt;a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/pipe.html" target="_blank"&gt;pipes&lt;/a&gt; are. In this application, we are going to see how much data we can stuff in a pipe before  we're told that the pipe is full, and the write would need to block.&lt;br /&gt;&lt;br /&gt;Linux offers a function called &lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man2/pipe.2.html" target="_blank"&gt;pipe2()&lt;/a&gt; which has the crucial ability to create a pipe in non-blocking mode. If it doesn't exist, we can create it ourselves, but we prefer the built in one if possible.&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: green;"&gt;#ifndef __linux__&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#error This program is specifically designed for Linux, even though it works elsewhere&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#endif&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;stdio.h&amp;gt; //puts(), fputs(), printf(), fprintf(), stderr&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;errno.h&amp;gt; //errno, perror(), EINTR, EAGAIN, EWOULDBLOCK&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;fcntl.h&amp;gt; //fcntl(), F_SETFL, F_GETFL, O_NONBLOCK, F_SETFD, F_GETFD, FD_CLOEXEC, and for some: O_CLOEXEC&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;dlfcn.h&amp;gt; //dlopen(), dlsym(), dlclose(), dlerror(), RTLD_LAZY&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;unistd.h&amp;gt; //pipe() used in our implementation, write(), close()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Lifted from: /usr/include/&amp;lt;arch&amp;gt;/bits/fcntl.h&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#ifndef O_CLOEXEC&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#define O_CLOEXEC       02000000        &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;/* set close_on_exec */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#endif&lt;/span&gt;&lt;br /&gt;&lt;span style="color: grey; font-style: italic;"&gt;//End lift&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;typedef&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; (*pipe2_t)(&lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; [&lt;/span&gt;&lt;span style="color: blue;"&gt;2&lt;/span&gt;&lt;span style="color: black;"&gt;], &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Implement the rather straight forward pipe2(), note: this function is of type: static pipe2_t&lt;/span&gt;&lt;br /&gt;&lt;span style="color: maroon;"&gt;static&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; our_pipe2(&lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; pipefd[&lt;/span&gt;&lt;span style="color: blue;"&gt;2&lt;/span&gt;&lt;span style="color: black;"&gt;], &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; flags)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; ret = pipe(pipefd);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (!ret) &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Success, pipe created&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//The built in pipe2() would not suffer from race conditions that the following code would succumb to in a threaded application&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (flags &amp;amp; O_NONBLOCK)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      fcntl(pipefd[&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;], F_SETFL, fcntl(pipefd[&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;], F_GETFL) | O_NONBLOCK);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      fcntl(pipefd[&lt;/span&gt;&lt;span style="color: blue;"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;], F_SETFL, fcntl(pipefd[&lt;/span&gt;&lt;span style="color: blue;"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;], F_GETFL) | O_NONBLOCK);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (flags &amp;amp; O_CLOEXEC)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      fcntl(pipefd[&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;], F_SETFD, fcntl(pipefd[&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;], F_GETFD) | FD_CLOEXEC);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      fcntl(pipefd[&lt;/span&gt;&lt;span style="color: blue;"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;], F_SETFD, fcntl(pipefd[&lt;/span&gt;&lt;span style="color: blue;"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;], F_GETFD) | FD_CLOEXEC);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt;(ret);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: maroon;"&gt;static&lt;/span&gt;&lt;span style="color: black;"&gt; pipe2_t pipe2 = our_pipe2; &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//pipe2() is initialized to our function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;size_t pipe_size() &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Manually determine the size of the system's pipe, for automatic, look up Linux specific F_GETPIPE_SZ&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Create a union for using a pipe, so usage is a bit more logical&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;union&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; pipefd[&lt;/span&gt;&lt;span style="color: blue;"&gt;2&lt;/span&gt;&lt;span style="color: black;"&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;struct&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; read;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; write;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    } side;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  } u;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  size_t amount = &lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;; &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//A pipe size of 0 signifies unknown&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (!pipe2(u.pipefd, O_NONBLOCK)) &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Note, here pipe2() is used&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;for&lt;/span&gt;&lt;span style="color: black;"&gt; (;;) &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Write to a pipe in a loop, the final amount should be the size of the pipe&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      ssize_t w = write(u.side.write, &amp;amp;amount, &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;sizeof&lt;/span&gt;&lt;span style="color: black;"&gt;(size_t)); &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Write a size_t to the pipe&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (w &amp;gt; &lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;) { amount += w; } &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Success, add amount written and then loop&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;else&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (w == &lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;) &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Pipe was closed, and we certainly didn't close it&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;        perror(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Pipe unexpectedly closed"&lt;/span&gt;&lt;span style="color: black;"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;        amount = &lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;; &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Reset to unknown, because an error occured&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;        &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;break&lt;/span&gt;&lt;span style="color: black;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;else&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;/* Error occured trying to write */&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (errno != EINTR) &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//And it wasn't an interruption, so something that needs handling&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;        &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; ((errno != EAGAIN) &amp;amp;&amp;amp; (errno != EWOULDBLOCK)) &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Failed to write to pipe - and it's nothing we'd fix&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;          perror(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Failed to write to pipe"&lt;/span&gt;&lt;span style="color: black;"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;          amount = &lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;; &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Reset to unknown, because an error occured&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;        &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Else, pipe is full, we're done!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;        &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;break&lt;/span&gt;&lt;span style="color: black;"&gt;; &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//In either case, we're done writing to the pipe&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Else If (errno == EINTR), we'd just loop and try again&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    close(u.side.read);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    close(u.side.write);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;else&lt;/span&gt;&lt;span style="color: black;"&gt; { perror(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Failed to create pipe"&lt;/span&gt;&lt;span style="color: black;"&gt;); }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt;(amount);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; main(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; argc, &lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; *&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; argv)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: maroon;"&gt;void&lt;/span&gt;&lt;span style="color: black;"&gt; *so = dlopen(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"libc.so.6"&lt;/span&gt;&lt;span style="color: black;"&gt;, RTLD_LAZY); &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Open the C library&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (so)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: maroon;"&gt;void&lt;/span&gt;&lt;span style="color: black;"&gt; *sym = dlsym(so, &lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"pipe2"&lt;/span&gt;&lt;span style="color: black;"&gt;); &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Grab the handle to pipe2() if it exists&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (sym) &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Success!&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      pipe2 = (pipe2_t)sym; &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Use the built in one instead of ours&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      puts(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Using system's pipe2()."&lt;/span&gt;&lt;span style="color: black;"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;else&lt;/span&gt;&lt;span style="color: black;"&gt; { puts(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Using our pipe2()."&lt;/span&gt;&lt;span style="color: black;"&gt;); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;else&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    puts(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Using our pipe2()."&lt;/span&gt;&lt;span style="color: black;"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    fprintf(stderr, &lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Could not open C library: %s&lt;/span&gt;&lt;span style="color: magenta;"&gt;\n&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"&lt;/span&gt;&lt;span style="color: black;"&gt;, dlerror());&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Here's the real work&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  size_t a = pipe_size();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (a) { printf(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Pipe size is: %zu&lt;/span&gt;&lt;span style="color: magenta;"&gt;\n&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"&lt;/span&gt;&lt;span style="color: black;"&gt;, a); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;else&lt;/span&gt;&lt;span style="color: black;"&gt; { fputs(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Could not determine pipe size.&lt;/span&gt;&lt;span style="color: magenta;"&gt;\n&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"&lt;/span&gt;&lt;span style="color: black;"&gt;, stderr); }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (so) { dlclose(so); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;/pre&gt;Here's how to compile and run it:  &lt;br /&gt;&lt;blockquote&gt;/tmp&amp;gt; gcc -Wall -o pipe_test pipe_test.c -ldl&lt;br /&gt;/tmp&amp;gt; ./pipe_test&lt;br /&gt;Using system's pipe2().&lt;br /&gt;Pipe size is: 65536&lt;br /&gt;/tmp&amp;gt;&lt;/blockquote&gt;Now pipe2() Was added to GLIBC in 2.9, yet this binary here according to &lt;i&gt;objdump&lt;/i&gt; only needs (E)GLIBC 2.2.5+. Here's the output from an older system with GLIBC 2.7, using the exact same binary created on a newer system:  &lt;br /&gt;&lt;blockquote&gt;/tmp&amp;gt; ./pipe_test&lt;br /&gt;Using our pipe2().&lt;br /&gt;Pipe size is: 65536&lt;br /&gt;/tmp&amp;gt;&lt;/blockquote&gt;Lastly, let me recap all the techniques we learned.  &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use &lt;i&gt;ldd&lt;/i&gt; and &lt;i&gt;objdump&lt;/i&gt; to see version requirements of binaries and libraries. &lt;/li&gt;&lt;li&gt;Statically link compiler and language libraries, such as libgcc and libstdc++.&lt;/li&gt;&lt;li&gt;Statically link selected libraries, while dynamically linking others.&lt;/li&gt;&lt;li&gt;Compile selected libraries with as little needed functionality as possible. &lt;/li&gt;&lt;li&gt;Pushing (E)GLIBC requirements down, by being wary of functions which have changed over time, and (E)GLIBC redirects calls to them in newly compiled programs by default.&lt;/li&gt;&lt;li&gt;Pushing (E)GLIBC requirements down by not directly using new functions, and instead working around their presence.&lt;/li&gt;&lt;/ul&gt;Doing all this, you'll still need to make different builds for different operating systems, and different architectures like x86 and ARM, but at least you won't be forced to for all different distros and versions thereof.&lt;br /&gt;&lt;br /&gt;One thing of note, it's possible to have Linux with different C libraries, and in those cases, you may as well be using a different Operating System. You'll be hard pressed to make complex programs compiled against one C library run on Linux which uses a different C library, where the needed one is not present. Thankfully though, all the mainstream desktop and server distros all use (E)GLIBC.&lt;br /&gt;&lt;br /&gt;In any case, the techniques you've learned here can also be applied to other setups too.&amp;nbsp; (E)GLIBC was only focused on in this article because of its popularity and its many gotchas, but many other libraries that you may use, particularly video and audio libraries have similar issues as well.</description><link>http://insanecoding.blogspot.com/2012/07/creating-portable-linux-binaries.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>5</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-5732990615606983833</guid><pubDate>Wed, 14 Dec 2011 15:58:00 +0000</pubDate><atom:updated>2011-12-14T14:01:25.135-08:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>GTK</category><category domain='http://www.blogger.com/atom/ns#'>File Dialog</category><category domain='http://www.blogger.com/atom/ns#'>crazy executives</category><category domain='http://www.blogger.com/atom/ns#'>GNOME</category><category domain='http://www.blogger.com/atom/ns#'>Mozilla</category><category domain='http://www.blogger.com/atom/ns#'>Political Correctness</category><category domain='http://www.blogger.com/atom/ns#'>debian</category><category domain='http://www.blogger.com/atom/ns#'>Windows</category><category domain='http://www.blogger.com/atom/ns#'>distribution</category><category domain='http://www.blogger.com/atom/ns#'>Firefox</category><category domain='http://www.blogger.com/atom/ns#'>competition</category><category domain='http://www.blogger.com/atom/ns#'>KDE</category><category domain='http://www.blogger.com/atom/ns#'>pure failure</category><category domain='http://www.blogger.com/atom/ns#'>compatibility</category><category domain='http://www.blogger.com/atom/ns#'>torture</category><category domain='http://www.blogger.com/atom/ns#'>Mac OS X</category><title>Progression and Regression of Desktop User Interfaces</title><description>As this Gregorian year comes to a close, with various new interfaces out now, and some new ones on the horizon, I decided to recap my personal experiences with user interfaces on the desktop, and see what the future will bring.&lt;br /&gt;&lt;br /&gt;When I was younger, there were a few desktop environments floating around, and I've seen a couple of them at school or a friend's house. But the first one I had on my own personal computer, and really played around with was Windows 3.&lt;br /&gt;&lt;br /&gt;Windows 3 came with something called Program Manager. Here's what it looked like:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-LGd15rvRKqA/TujJXGRNAKI/AAAAAAAAAHk/c26JCwBHpDk/s1600/Program_Manager.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 210px;" src="http://4.bp.blogspot.com/-LGd15rvRKqA/TujJXGRNAKI/AAAAAAAAAHk/c26JCwBHpDk/s320/Program_Manager.png" alt="" id="BLOGGER_PHOTO_ID_5686015928212193442" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-F9Y_kTh71Bw/TujJXdQsy0I/AAAAAAAAAHs/Z3yG7hGFsb8/s1600/program-manager-internet-explorer.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://4.bp.blogspot.com/-F9Y_kTh71Bw/TujJXdQsy0I/AAAAAAAAAHs/Z3yG7hGFsb8/s320/program-manager-internet-explorer.png" alt="" id="BLOGGER_PHOTO_ID_5686015934384098114" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The basic idea was that you had a "start screen", where you had your various applications grouped by their general category. Within each of these "groups", you had shortcuts to the specific applications. Now certain apps like a calculator you only used in a small window, but most serious apps were only used maximized. If you wanted to switch to another running app, you either pressed the alt+tab keyboard shortcut to cycle through them, or you minimized everything, where you then saw a screen listing all the currently running applications.&lt;br /&gt;&lt;br /&gt;Microsoft also shipped a very nice file manager, known as "File Manager", which alone made it useful to use Windows. It was rather primitive though, and various companies released various add-ons for it to greatly enhance its abilities. I particularly loved Wiz File Manager Pro.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-f3kvvBB5TGI/TujmZowSikI/AAAAAAAAAH8/0nTN6sTK34c/s1600/fileman.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/-f3kvvBB5TGI/TujmZowSikI/AAAAAAAAAH8/0nTN6sTK34c/s320/fileman.png" alt="" id="BLOGGER_PHOTO_ID_5686047857666329154" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Various companies also made add-ons for Program Manager, such as to allow nested groups, or shortcuts directly on the main screen outside of a group, or the ability to change the icons of selected groups. Microsoft would've probably built some of these add-ons in if it continued development of Program Manager.&lt;br /&gt;&lt;br /&gt;Now not everyone used Windows all the time back then, but only selectively started it up when they wanted something from it. I personally did everything in DOS unless I wanted to use a particular Windows app, such as file management or painting, or copying and pasting stuff around. Using Windows all the time could be annoying as it slowed down some DOS apps, or made some of them not start at all due to lack of memory and other issues.&lt;br /&gt;&lt;br /&gt;In the summer of 1995, Microsoft released Windows 4 to the world. It came bundled with MS-DOS 7, and provided a whole new user experience.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-VDrDcboMELI/Tujo1PoXc-I/AAAAAAAAAII/BEtbuoVwtcg/s1600/windows95.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://2.bp.blogspot.com/-VDrDcboMELI/Tujo1PoXc-I/AAAAAAAAAII/BEtbuoVwtcg/s320/windows95.png" alt="" id="BLOGGER_PHOTO_ID_5686050530981802978" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now the back-most window, the "desktop", no longer contained a list of the running programs (in explorer.exe mode), but rather you could put your own shortcuts and groups and groups of groups there. Rather running programs would appear at the bottom of the screen in a "taskbar". The taskbar now also contained a clock, and a "start menu", to launch applications. Some always running applications which were meant to be background tasks appeared as a tiny icon next to the clock in an area known as a "tray".&lt;br /&gt;&lt;br /&gt;This was a major step forward in usability. Now, no matter which application you were currently using, you could see all the ones that were currently running on the edge of your screen. You could also easily click on one of them to switch to it. You didn't need to minimize all to see them anymore. Thanks to the start menu, you could also easily launch all your existing programs without needing to minimize all back down to Program Manager. The clock always being visible was also a nice touch.&lt;br /&gt;&lt;br /&gt;Now when this came out, I could appreciate these improvements, but at the same time, I also hated it. A lot of us were using 640x480 resolutions on 14" screens back then. Having something steal screen space was extremely annoying. Also with how little memory systems had back at the time (4 or 8 MB of RAM), you generally weren't running more than 2 or 3 applications at a time and could not really appreciate the benefits of having an always present taskbar. Some people played with taskbar auto-hide because of this.&lt;br /&gt;&lt;br /&gt;The start menu was also a tad ridiculous. Lots of clicks were needed to get anywhere. The default appearance also had too many useless things on it.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-qMXIhbbGRWM/TujrotSaWaI/AAAAAAAAAIU/BPeKanOiPag/s1600/startmenu.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 320px;" src="http://3.bp.blogspot.com/-qMXIhbbGRWM/TujrotSaWaI/AAAAAAAAAIU/BPeKanOiPag/s320/startmenu.png" alt="" id="BLOGGER_PHOTO_ID_5686053614139365794" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Did anyone actually use help? Did most people launch things from documents? Microsoft released a nice collection of utilities called "PowerToys" which contained "TweakUI" which you could use to make things work closer to how you want.&lt;br /&gt;&lt;br /&gt;The default group programs installed to within the start menu was quite messy though. Software installers would not organize their shortcuts into the groups that Windows came with, but each installed their apps into their own unique group. Having 50 submenus pop out was rather unwieldy, and I personally organized each app after I installed it. Grouping into "System Tools", "Games", "Internet Related Applications", and so on. It was annoying to manually do all this though, as when removing an app, you had to remove its group manually. On upgrades, one would also have to readjust things each time too.&lt;br /&gt;&lt;br /&gt;Windows 4 also came with the well known Windows Explorer file manager to replace the older one. It was across the board better than the vanilla version of File Manager that shipped with Windows 3.&lt;br /&gt;&lt;br /&gt;I personally started dual booting MS-DOS 6.22 + Windows for Workgroups 3.11 and Windows 95 (and later tri-booted with OS/2 Warp). Basically I used DOS and Windows for pretty much everything, and Windows 95 for those apps that required it. Although I managed to get most apps to work with Windows 3 using Win32s.&lt;br /&gt;&lt;br /&gt;As I got a larger screen and more RAM though, I finally started to appreciate what Windows 4 offered, and started to use it almost exclusively. I still exited Windows into DOS 7 though for games that needed to use more RAM, or ran quicker that way on our dinky processors from back then.&lt;br /&gt;&lt;br /&gt;Then Windows 4.10 / Internet Explorer 4 came out which offered a couple of improvements. First was "quick launch" which allowed you to put shortcuts directly on your taskbar. You could also make more than one taskbar and put all your shortcuts on it. I personally loved this feature, I put one taskbar on top of my screen, and loaded it with shortcuts to all my common applications, and had one on the bottom for classical use. Now I only had to dive into the start menu for applications I rarely used.&lt;br /&gt;&lt;br /&gt;It also offered a feature called "active desktop" which made the background of the desktop not just an image, but a web page. I initially loved the feature, as I edited my own page, and stuck in an input line which I would use to launch a web browser to my favorite search engine at the time (which changed monthly) with my text already searched for. After a while active desktop got annoying though, as every time IE crashed, it disabled it, and you had to deal with extra error messages, and go turn it on manually.&lt;br /&gt;&lt;br /&gt;By default this new version also made every Windows Explorer window have this huge sidebar stealing your precious screen space. Thankfully though, you could turn it off.&lt;br /&gt;&lt;br /&gt;All in all though, as our CPUs got faster, RAM became cheaper, and large screens more available, this interface was simply fantastic. I stopped booting into other OSs, or exiting Windows itself.&lt;br /&gt;&lt;br /&gt;Then Windows 5 came out for consumers, and UI wise, there weren't really any significant changes. The default look used these oversized bars and buttons on each window, but one could easily turn that off. The start menu got a bit of a rearrangement to now feature your most used programs up front, and various actions got pushed off to the side. Since I already put my most used programs on my quick launch on top, this start menu was a complete waste of space. Thankfully, it could also be turned off. I still kept using Windows 98 though, as I didn't see any need for this new Windows XP, and it was just a memory hog in comparison at the time.&lt;br /&gt;&lt;br /&gt;What was more interesting to me however was that at work, all our machines ran Linux with GNOME and KDE. When I first started working there, they made me take a course on how to use Emacs, as every programmer needs a text editor. I was greatly annoyed by the thing however, where was my shift highlight with shift+delete and shift+insert or ctrl+x and ctrl+v cut and paste? Thankfully though I soon found gedit and kedit which was like edit/notepad/wordpad but for Linux.&lt;br /&gt;&lt;br /&gt;Now I personally don't use a lot of windowsy type software often. My primary usage of a desktop consists of using a text editor, calculator, file manager, console/terminal/prompt, hex editor, paint, cd/dvd burner, and web browser. Only rarely do I launch anything else. Perhaps a PDF, CHM, or DJVU reader when I need to read something.&lt;br /&gt;&lt;br /&gt;After using Linux with GNOME/KDE at work for a while, I started to bring more of my work home with me and wanted these things installed on my own personal computer. So dual booting Windows 98 + Linux was the way to go. I started trying to tweak my desktop a bit, and found that KDE was way more capable than GNOME, as were most of their similar apps that I was using. KDE basically offered me everything that I loved about Windows 98, but on steroids. KWrite/KATE was notepad/wordpad but on steroids. The syntax highlighting was absolutely superb. KCalc was a fine calc.exe replacement. Konqueror made Windows Explorer seem like a joke in comparison.&lt;br /&gt;&lt;br /&gt;Konqueror offered network transparency, thumbnails of everything rather quickly, even of text files (no pesky thumbs.db either!). An info list view which was downright amazing:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-IoKmHGtj0HE/Tuj4EwBsoeI/AAAAAAAAAIg/tFdhJ1qhkcM/s1600/konq.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 130px;" src="http://2.bp.blogspot.com/-IoKmHGtj0HE/Tuj4EwBsoeI/AAAAAAAAAIg/tFdhJ1qhkcM/s320/konq.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5686067290050437602" /&gt;&lt;/a&gt;This is a must have feature here. Too often are documents distributed under meaningless file names. With this, and many other small features, nothing else I've seen has even come close to Konqueror in terms of file management.&lt;br /&gt;&lt;br /&gt;Konsole was just like my handy DOS Prompt, except with tab support, and better maximizing, and copy and paste support. KHexEdit was simply better than anything I had for free on Windows. KolourPaint is mspaint.exe with support for way more image formats. K3b was also head and shoulders above Easy CD Creator or Nero Burning ROM. For Web Browsers, I was already using Mozilla anyway on Windows, and had the same option on Linux too.&lt;br /&gt;&lt;br /&gt;For the basic UI, not only did KDE have everything I liked about Windows, it came with an organized start menu. Which also popped out directly, instead from a "programs" submenu.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-5r8L9sci1ds/Tuj5oNzFjuI/AAAAAAAAAIs/ojcvSTR0NJY/s1600/kdestart.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 229px; height: 191px;" src="http://4.bp.blogspot.com/-5r8L9sci1ds/Tuj5oNzFjuI/AAAAAAAAAIs/ojcvSTR0NJY/s320/kdestart.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5686068998849269474" /&gt;&lt;/a&gt;&lt;br /&gt;The taskbar was also enhanced that I could stick various applets on it. I could stick volume control &lt;span style="font-weight:bold;"&gt;directly&lt;/span&gt; on it. Not a button which popped out a slider, the sliders themselves could appear on the taskbar. Now for example, I could easily adjust my microphone volume directly, without popping up or clicking on anything extra. There was an eyedropper which you could just push to find out the HTML color of anything appearing on the screen - great for web developers. Another thing which I absolutely love, I can see all my removable devices listed directly on my taskbar. If I have a disk in my drive, I see an icon for that drive appearing directly on my taskbar, and I can browse it, burn to it, eject it, whatever. With this, everything I need is basically at my finger tips.&lt;br /&gt;&lt;br /&gt;Before long I found myself using Linux/KDE all the time. On newer machines I started to dual boot Windows XP with Linux/KDE, so I could play the occasional Windows game when I wanted to, but for real work, I'd be using Linux.&lt;br /&gt;&lt;br /&gt;Then KDE 4 comes out, and basically half the stuff I loved about KDE was removed. No longer is it Windows on steroids. Now KDE 4.0 was not intended for public consumption. Somehow all the distros except for Debian seemed to miss that. Everyone wants to blame KDE for miscommunicating this, but it's quite clear 4.0 was only for developers if you watched the KDE 4 release videos. Any responsible package maintainer with a brain in their skull should've also realized that 4.0 was not ready for prime time. Yet it seems the people managing most distros are idiots that just need the "latest" version of everything, ignoring if it's better or not, or even stable.&lt;br /&gt;&lt;br /&gt;At the time, all these users were upset, and all started switching to GNOME. I don't know why anyone who truly loved the power KDE gave you would do that. If KDE 3 &gt; GNOME 2 &gt; KDE 4, why did people migrate to GNOME 2 when they could just not "upgrade" from KDE 3? It seems to me that people never really appreciated what KDE offers in the first place if they bothered moving to GNOME instead of keeping what was awesome.&lt;br /&gt;&lt;br /&gt;Nowadays people tell me that KDE 4 has feature parity with KDE 3, but I have no idea what they're talking about. The Konqueror info list feature that I described above still doesn't seem to exist in KDE 4. You can no longer have applets directly on your taskbar. Now I have to click a button to pop up a list of my devices, and only then can I do something with them. No way to quickly glance to see what is currently plugged in. Konsole's tabs now stretch to the full width of your screen for some pointless reason. If you want to switch between tabs with your mouse, prepare for carpal tunnel syndrome. Who thought that icons should grow if they can? It's exactly like those idiotic theoretical professors who spout that CPU usage must be maximized at all times, and therefore use algorithms that schedule things for maximum power draw, despite that in normal cases performance does not improve by using these algorithms. I'd rather pack in more data if possible, having multiple columns of information instead of just huge icons.&lt;br /&gt;&lt;br /&gt;KHexEdit has also been completely destroyed. No longer is the column count locked to hex (16). I can't imagine anyone who seriously uses a hex editor designed the new version. For some reason, KDE now also has to act like your mouse only has one button, and right click context menus vanished from all over the place. It's like the entire KDE development team got invaded by Mac and GNOME users who are too stupid to deal with anything other than a big button in the middle of the screen.&lt;br /&gt;&lt;br /&gt;Over in the Windows world. Windows 6 (with 6.1 comically being consumerized as "Windows 7") came out with a bit of a revamp. The new start menu seems to fail basic quality assurance tests for anything other than default settings. Try to set things to offer a classic start menu, this is what you get:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-Mt2z6cUg-dQ/Tuj-8q2QzqI/AAAAAAAAAI4/IV8Nn-Le6PQ/s1600/windows7.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 267px; height: 320px;" src="http://1.bp.blogspot.com/-Mt2z6cUg-dQ/Tuj-8q2QzqI/AAAAAAAAAI4/IV8Nn-Le6PQ/s320/windows7.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5686074847802740386" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you use extra large icons for your grandparents, you also find that half of the Control Panel is now inaccessible. Ever since Bill Gates left, it seems Windows is going down the drain.&lt;br /&gt;&lt;br /&gt;But hardly are problems solely for KDE and Windows, GNOME 3 is also a major step back according to what most people tell me. Many of these users are now migrating to XFCE. If you like GNOME 2, why are you migrating to something else for? And what is it with people trying to fix what isn't broken? If you want to offer an alternate interface, great, but why break or remove the one you already have?&lt;br /&gt;&lt;br /&gt;Now a new version of Windows is coming out with a new interface being called "Metro". They should really be calling it "Retro". It's Windows 3 Program Manager with a bunch of those third party add-ons, with a more modern look to it. Gone is the Windows 4+ taskbar so you can see what was running, and easily switch applications via mouse. Now you'll need to press the equivalent of a minimize all to get to the actual desktop. Another type of minimize to get back to Program Manager to launch something else, or "start screen" as they're now calling it.&lt;br /&gt;&lt;br /&gt;So say goodbye to all the usability and productivity advantages Windows 4 offered us, they want to take us back to the "dark ages" of modern computing. Sure a taskbar-less interface makes sense on handheld devices with tiny screens or low resolution, but on modern 19"+ screens? The old Windows desktop+taskbar in the upcoming version of Windows is now just another app in their Metro UI. So "Metro" apps won't appear on the classic taskbar, and "classic" applications won't appear on the Metro desktop where running applications are listed.&lt;br /&gt;&lt;br /&gt;I'm amazed at how self destructive the entire market became over the last few years. I'm not even sure who to blame, but someone has to do something about it. It's nice to see that a small group of people took KDE 3.5, and are continuing to develop it, but they're rebranding everything with crosses everywhere and calling it "Trinity" desktop. Just what we need, to bring religious issues now into desktop environments. What next? The political desktop?</description><link>http://insanecoding.blogspot.com/2011/12/progression-and-regression-of-desktop.html</link><author>noreply@blogger.com (insane coder)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-LGd15rvRKqA/TujJXGRNAKI/AAAAAAAAAHk/c26JCwBHpDk/s72-c/Program_Manager.png' height='72' width='72'/><thr:total>17</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-1934168996693621718</guid><pubDate>Tue, 29 Nov 2011 20:26:00 +0000</pubDate><atom:updated>2011-11-29T16:50:28.509-08:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>files</category><category domain='http://www.blogger.com/atom/ns#'>competition</category><category domain='http://www.blogger.com/atom/ns#'>API</category><category domain='http://www.blogger.com/atom/ns#'>GCC</category><category domain='http://www.blogger.com/atom/ns#'>Optimization</category><title>Reading in an entire file at once in C++, part 2</title><description>Last week I discussed &lt;a href="http://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html"&gt;6 different methods on how to quickly get an entire file into a C++ string&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The conclusion was that the straight forward method was the ideal method, this was verified across several compilers. Since then, people asked me a number of questions.&lt;br /&gt;&lt;br /&gt;What if I want to use a vector instead of a string, are the speeds different?&lt;br /&gt;Forget C++ containers, what about directly into a manually allocated buffer?&lt;br /&gt;What about copying into a buffer via mmap?&lt;br /&gt;What do these various cases say about compilers or their libraries? Can this indicate what they're good or bad at compiling?&lt;br /&gt;&lt;br /&gt;So to establish some baseline numbers, I created an application which reads the same files the same amount of times using the fastest method possible. It directly creates a buffer aligned to the partition's blocking factor, informs the OS to do the fastest possible sequential read, and then reads the file directly into the buffer. I also tested the suggested method to mmap a file, and copy the contents from there to an allocated buffer. The times achieved for these were 5 and 9 respectively. The latter is slower because of the extra memcpy() required, you want to read directly into your destination buffer whenever possible. The fastest time I now achieved should more or less be the fastest theoretical limit I'm able to get with my hardware. Both GCC and LLVM got the exact same times. I did not test with VC++ here as it doesn't support POSIX 2008.&lt;br /&gt;&lt;br /&gt;Now regarding our 6 methods from last time, all of them except the Rdbuf method are possible with std::vector, since there is no std::vector based std::istream.&lt;br /&gt;&lt;br /&gt;An interesting thing to note is that C++ string implementations vary greatly from implementation to implementation. Some offer optimizations for very small strings, some offer optimizations for frequent copies, by using reference counting. Some always ensure the string ends with a 0 byte so you can immediately pass them as a C string. In this latter case, operations which operate on strings as a range are rather quick, as the data is copied, then a 0 is appended. Whereas a loop which constantly pushes bytes on the back will have to needlessly set the extra trailing byte to 0 each time. Vector implementations on the other hand don't need to worry about a trailing 0 byte, and generally don't try to internally use all kinds of elaborate storage methods. So if std::vector works for you, you may want to use that.&lt;br /&gt;&lt;br /&gt;Let's review times for the 5 applicable methods with our various compilers.&lt;br /&gt;&lt;br /&gt;GCC 4.6 with a vector:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Method&lt;/th&gt;&lt;th&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;23.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C++&lt;/td&gt;&lt;td&gt;22.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Iterator&lt;/td&gt;&lt;td&gt;73&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Assign&lt;/td&gt;&lt;td&gt;81.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Copy&lt;/td&gt;&lt;td&gt;68&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Whereas with a string:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Method&lt;/th&gt;&lt;th&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;24.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C++&lt;/td&gt;&lt;td&gt;24.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Iterator&lt;/td&gt;&lt;td&gt;64.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Assign&lt;/td&gt;&lt;td&gt;68&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Copy&lt;/td&gt;&lt;td&gt;63&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;We see that with a vector, the basic methods became a bit faster, but interestingly enough, the others got slower. However, which methods are superior to the others have remained the same.&lt;br /&gt;&lt;br /&gt;Now for LLVM 3 with a vector:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Method&lt;/th&gt;&lt;th&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C++&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Iterator&lt;/td&gt;&lt;td&gt;860&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Assign&lt;/td&gt;&lt;td&gt;1328&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Copy&lt;/td&gt;&lt;td&gt;930&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Versus for string:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Method&lt;/th&gt;&lt;th&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;7.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C++&lt;/td&gt;&lt;td&gt;7.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Iterator&lt;/td&gt;&lt;td&gt;110&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Assign&lt;/td&gt;&lt;td&gt;102&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Copy&lt;/td&gt;&lt;td&gt;97&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;With LLVM, everything is slower with a vector, and for the more complex solutions, much much slower. There's two interesting things we can see about LLVM though. For more straight forward logic, their compiler's optimizations are extremely smart. The speeds approach the theoretical best. I did some profiling on GCC and LLVM, as they're using the same C and C++ libraries, and found that in the straight C/C++ methods for my test program, GCC made 300 memory allocations, but LLVM made only 200. LLVM apparently is smart enough to see inside the various allocations, skip the ones that aren't needed, and place the data directly into the output buffer. But for complex code, LLVM's optimizations aren't that great. In the case of vectors and iterators, downright awful. Someone should file some bug reports with them.&lt;br /&gt;&lt;br /&gt;Now for Visual C++ 2010 using vector:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Method&lt;/th&gt;&lt;th&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;17.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C++&lt;/td&gt;&lt;td&gt;18.7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Iterator&lt;/td&gt;&lt;td&gt;180.6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Assign&lt;/td&gt;&lt;td&gt;159.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Copy&lt;/td&gt;&lt;td&gt;165.6&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;And string:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Method&lt;/th&gt;&lt;th&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;16.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C++&lt;/td&gt;&lt;td&gt;20.4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Iterator&lt;/td&gt;&lt;td&gt;224.4&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Assign&lt;/td&gt;&lt;td&gt;222.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Copy&lt;/td&gt;&lt;td&gt;320&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;We see here that the Copy method, which uses push_back() got a huge performance improvement. This seems to indicate that the STL implementation adds a 0 at the end of each operation, especially push_back(), instead of just when c_str() is called. Otherwise, string is faster.&lt;br /&gt;&lt;br /&gt;It's also sad to see that GCC while winning all the cases where iterators were involved, was significantly slower in all the straight forward cases. This seems to indicate that GCC has the smartest optimizations, but fails to optimize well when the logic is straightforward. Someone should look into that.&lt;br /&gt;&lt;br /&gt;It seems if you're trying to hold a collection of bytes, or whatever your wchar_t is, but don't care about the specialties of any particular container, as long as you don't push_back() a lot, string seems to be faster.&lt;br /&gt;&lt;br /&gt;Finally, here's a table of all the compilers and methods I tested ordered by speed:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;tr&gt;&lt;th&gt;Method&lt;/th&gt;&lt;th&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POSIX&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLVM 3.0 s C/C++&lt;/td&gt;&lt;td&gt;7.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLVM 3.0 v C/C++&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MMAP&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2010 s C&lt;/td&gt;&lt;td&gt;16.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2010 v C&lt;/td&gt;&lt;td&gt;17.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2005 s C&lt;/td&gt;&lt;td&gt;18.3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2010 v C++&lt;/td&gt;&lt;td&gt;19.7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2010 s C++&lt;/td&gt;&lt;td&gt;20.4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2005 s C++&lt;/td&gt;&lt;td&gt;21&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GCC 4.6 v C++&lt;/td&gt;&lt;td&gt;22.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GCC 4.6 v C&lt;/td&gt;&lt;td&gt;23.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2005 v C&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GCC 4.6 s C/C++&lt;/td&gt;&lt;td&gt;24.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2005 v C++&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLVM 3.0 s Rdbuf&lt;/td&gt;&lt;td&gt;31.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GCC 4.6 s Rdbuf&lt;/td&gt;&lt;td&gt;32.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GCC 4.6 s Copy&lt;/td&gt;&lt;td&gt;63&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GCC 4.6 s Iterator&lt;/td&gt;&lt;td&gt;64.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GCC 4.6 s Assign&lt;/td&gt;&lt;td&gt;68&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GCC 4.6 v Copy&lt;/td&gt;&lt;td&gt;68&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GCC 4.6 v Iterator&lt;/td&gt;&lt;td&gt;73&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GCC 4.6 v Assign&lt;/td&gt;&lt;td&gt;81.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLVM 3.0 s Copy&lt;/td&gt;&lt;td&gt;97&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLVM 3.0 s Assign&lt;/td&gt;&lt;td&gt;102&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLVM 3.0 s Iterator&lt;/td&gt;&lt;td&gt;110&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2010 v Assign&lt;/td&gt;&lt;td&gt;159.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2010 v Copy&lt;/td&gt;&lt;td&gt;165.6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2005 v Copy&lt;/td&gt;&lt;td&gt;172&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2010 s Rdbuf&lt;/td&gt;&lt;td&gt;176.2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2010 v Iterator&lt;/td&gt;&lt;td&gt;180.6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2005 s Rdbuf&lt;/td&gt;&lt;td&gt;199&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2005 s Iterator&lt;/td&gt;&lt;td&gt;209.3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2005 s Assign&lt;/td&gt;&lt;td&gt;221&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2010 s Assign&lt;/td&gt;&lt;td&gt;222.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2010 s Iterator&lt;/td&gt;&lt;td&gt;224.4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2010 s Copy&lt;/td&gt;&lt;td&gt;320&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2005 v Iterator&lt;/td&gt;&lt;td&gt;370&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2005 v Assign&lt;/td&gt;&lt;td&gt;378&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VC 2005 s Copy&lt;/td&gt;&lt;td&gt;483.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLVM 3.0 v Iterator&lt;/td&gt;&lt;td&gt;860&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLVM 3.0 v Copy&lt;/td&gt;&lt;td&gt;930&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LLVM 3.0 v Assign&lt;/td&gt;&lt;td&gt;1328&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</description><link>http://insanecoding.blogspot.com/2011/11/reading-in-entire-file-at-once-in-c.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-33811130938884247</guid><pubDate>Tue, 22 Nov 2011 23:27:00 +0000</pubDate><atom:updated>2013-04-02T19:02:30.474-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>files</category><category domain='http://www.blogger.com/atom/ns#'>competition</category><category domain='http://www.blogger.com/atom/ns#'>good code</category><category domain='http://www.blogger.com/atom/ns#'>API</category><category domain='http://www.blogger.com/atom/ns#'>GCC</category><category domain='http://www.blogger.com/atom/ns#'>insane ideas</category><category domain='http://www.blogger.com/atom/ns#'>Optimization</category><title>How to read in a file in C++</title><description>So here's a simple question, what is the correct way to read in a file completely in C++?&lt;br /&gt;&lt;br /&gt;Various people have various solutions, those who use the C API, C++ API, or some variation of tricks with iterators and algorithms. Wondering which method is the fastest, I thought I might as well put the various options to the test, and the results were surprising.&lt;br /&gt;&lt;br /&gt;First, let me propose an API that we'll be using for the function. We'll send a function a C string (char *) of a filename, and we'll get back a C++ string (std::string) of the file contents. If the file cannot be opened, we'll throw an error why that is so. Of course you're welcome to change these functions to receive and return whatever format you prefer, but this is the prototype we'll be operating on:&lt;br /&gt;&lt;pre&gt;std::string get_file_contents(const char *filename);&lt;/pre&gt;&lt;br /&gt;Our first technique to consider is using the C API to read directly into a string. We'll open a file using fopen(), calculate the file size by seeking to the end, and then size a string appropriately. We'll read the contents into the string, and then return it.&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: green;"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;cstdio&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;cerrno&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;std::string get_file_contents(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *filename)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  std::FILE *fp = std::fopen(filename, &lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"rb"&lt;/span&gt;&lt;span style="color: black;"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (fp)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    std::string contents;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    std::fseek(fp, &lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;, SEEK_END);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    contents.resize(std::ftell(fp));&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    std::rewind(fp);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    std::fread(&amp;amp;contents[&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;], &lt;/span&gt;&lt;span style="color: blue;"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;, contents.size(), fp);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    std::fclose(fp);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt;(contents);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;throw&lt;/span&gt;&lt;span style="color: black;"&gt;(errno);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;I'm dubbing this technique "method C". This is more or less the technique of any proficient C++ programmer who prefers C style I/O would look like.&lt;br /&gt;&lt;br /&gt;The next technique we'll review is basically the same idea, but using C++ streams instead.&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: green;"&gt;#include &amp;lt;fstream&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;cerrno&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;std::string get_file_contents(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *filename)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  std::ifstream in(filename, std::ios::in | std::ios::binary);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (in)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    std::string contents;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    in.seekg(&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;, std::ios::end);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    contents.resize(in.tellg());&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    in.seekg(&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;, std::ios::beg);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    in.read(&amp;amp;contents[&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;], contents.size());&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    in.close();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt;(contents);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;throw&lt;/span&gt;&lt;span style="color: black;"&gt;(errno);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;I'm dubbing this technique "method C++". Again, more or less a straight forward C++ implementation based on the same principals as before.&lt;br /&gt;&lt;br /&gt;The next technique people consider is using istreambuf_iterator. This iterator is designed for really fast iteration out of stream buffers (files) in C++.&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: green;"&gt;#include &amp;lt;fstream&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;streambuf&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;cerrno&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;std::string get_file_contents(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *filename)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  std::ifstream in(filename, std::ios::in | std::ios::binary);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (in)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt;(std::string((std::istreambuf_iterator&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;(in)), std::istreambuf_iterator&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;()));&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;throw&lt;/span&gt;&lt;span style="color: black;"&gt;(errno);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;This method is liked by many because of how little code is needed to implement it, and you can read a file directly into all sorts of containers, not just strings. The method was also popularized by the &lt;a href="http://www.amazon.com/gp/product/0201749629/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0201749629&amp;amp;linkCode=as2&amp;amp;tag=insacodi-20"&gt;Effective STL&lt;/a&gt;&lt;img alt="" border="0" class="hioyqmdriwomkxxppfkw" height="1" src="http://www.assoc-amazon.com/e/ir?t=insacodi-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0201749629" style="border: none !important; margin: 0px !important;" width="1" /&gt; book. I'm dubbing the technique "method iterator".&lt;br /&gt;&lt;br /&gt;Now some have looked at the last technique, and felt it could be optimized further, since if the string has an idea in advance how big it needs to be, it will reallocate less. So the idea is to reserve the size of the string, then pull the data in.&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: green;"&gt;#include &amp;lt;fstream&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;streambuf&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;cerrno&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;std::string get_file_contents(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *filename)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  std::ifstream in(filename, std::ios::in | std::ios::binary);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (in)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    std::string contents;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    in.seekg(&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;, std::ios::end);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    contents.reserve(in.tellg());&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    in.seekg(&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;, std::ios::beg);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    contents.assign((std::istreambuf_iterator&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;(in)), std::istreambuf_iterator&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;());&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    in.close();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt;(contents);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;throw&lt;/span&gt;&lt;span style="color: black;"&gt;(errno);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;I will call this technique "method assign", since it uses the string's assign function.&lt;br /&gt;&lt;br /&gt;Some have questioned the previous function, as assign() in some implementations may very well replace the internal buffer, and therefore not benefit from reserving. Better to call push_back() instead, which will keep the existing buffer if no reallocation is needed.&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: green;"&gt;#include &amp;lt;fstream&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;streambuf&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;algorithm&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;iterator&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;cerrno&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;std::string get_file_contents(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *filename)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  std::ifstream in(filename, std::ios::in | std::ios::binary);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (in)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    std::string contents;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    in.seekg(&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;, std::ios::end);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    contents.reserve(in.tellg());&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    in.seekg(&lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;, std::ios::beg);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    std::copy((std::istreambuf_iterator&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;(in)), std::istreambuf_iterator&amp;lt;&lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;(), std::back_inserter(contents));&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    in.close();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt;(contents);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;throw&lt;/span&gt;&lt;span style="color: black;"&gt;(errno);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Combining std::copy() and std::back_inserter(), we can achieve our goal. I'm labeling this technique "method copy".&lt;br /&gt;&lt;br /&gt;Lastly, some want to try another approach entirely. C++ streams have some very fast copying to another stream via operator&amp;lt;&amp;lt; on their internal buffers. Therefore, we can copy directly into a string stream, and then return the string that string stream uses.&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: green;"&gt;#include &amp;lt;fstream&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;sstream&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;cerrno&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;std::string get_file_contents(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *filename)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  std::ifstream in(filename, std::ios::in | std::ios::binary);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (in)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    std::ostringstream contents;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    contents &amp;lt;&amp;lt; in.rdbuf();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    in.close();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt;(contents.str());&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;throw&lt;/span&gt;&lt;span style="color: black;"&gt;(errno);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;We'll call this technique "method rdbuf".&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now which is the fastest method to use if all you actually want to do is read the file into a string and return it? The exact speeds in relation to each other may vary from one implementation to another, but the overall margins between the various techniques should be similar.&lt;br /&gt;&lt;br /&gt;I conducted my tests with libstdc++ and GCC 4.6, what you see may vary from this.&lt;br /&gt;&lt;br /&gt;I tested with multiple megabyte files, reading in one after another, and repeated the tests a dozen times and averaged the results.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Method&lt;/th&gt;&lt;th&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;24.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C++&lt;/td&gt;&lt;td&gt;24.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Iterator&lt;/td&gt;&lt;td&gt;64.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Assign&lt;/td&gt;&lt;td&gt;68&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Copy&lt;/td&gt;&lt;td&gt;62.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Rdbuf&lt;/td&gt;&lt;td&gt;32.5&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Ordered by speed:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Method&lt;/th&gt;&lt;th&gt;Duration&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;C/C++&lt;/td&gt;&lt;td&gt;24.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Rdbuf&lt;/td&gt;&lt;td&gt;32.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Copy&lt;/td&gt;&lt;td&gt;62.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Iterator&lt;/td&gt;&lt;td&gt;64.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Assign&lt;/td&gt;&lt;td&gt;68&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;These results are rather interesting. There was no speed difference at all whether using the C or C++ API for reading a file. This should be obvious to us all, but yet many people strangely think that the C API has less overhead. The straight forward vanilla methods were also faster than anything involving iterators.&lt;br /&gt;&lt;br /&gt;C++ stream to stream copying is really fast. It probably only took a bit longer than the vanilla method due to some reallocations needed. If you're doing disk file to disk file though, you probably want to consider this option, and go directly from in stream to out stream.&lt;br /&gt;&lt;br /&gt;Using the istreambuf_iterator methods while popular and concise are actually rather slow. Sure they're faster than istream_iterators (with skipping turned off), but they can't compete with more direct methods.&lt;br /&gt;&lt;br /&gt;A C++ string's internal assign() function, at least in libstdc++, seems to throw away the existing buffer (at the time of this writing), so reserving then assigning is rather useless. On the other hand, reading directly into a string, or a different container for that matter, isn't necessarily your most optimal solution where iterators are concerned. Using the external std::copy() function, along with back inserting after reservation is faster than straight up initialization. You might want to consider this method for inserting into some other containers. In fact, I found that std::copy() of istreambuf_iterators with back inserter into an std::deque to be faster than straight up initialization (81 vs 88.5), despite a Deque not being able to reserve room in advance (nor does such make sense with a Deque).&lt;br /&gt;&lt;br /&gt;I also found this to be a cute way to get a file into a container backwards, despite a Deque being rather useless for working with file contents.&lt;br /&gt;&lt;pre&gt;std::deque&amp;lt;char&amp;gt; contents;&lt;br /&gt;std::copy((std::istreambuf_iterator&amp;lt;char&amp;gt;(in)), std::istreambuf_iterator&amp;lt;char&amp;gt;(), std::front_inserter(contents));&lt;/pre&gt;&lt;br /&gt;Now go out there and speed up your applications!&lt;br /&gt;&lt;br /&gt;If there's any demand, I'll see about performing these tests with other C++ implementations.</description><link>http://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>15</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-474153468529086324</guid><pubDate>Sat, 19 Nov 2011 20:18:00 +0000</pubDate><atom:updated>2011-11-19T12:42:17.228-08:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>bugs</category><category domain='http://www.blogger.com/atom/ns#'>pure failure</category><category domain='http://www.blogger.com/atom/ns#'>compatibility</category><category domain='http://www.blogger.com/atom/ns#'>linux</category><category domain='http://www.blogger.com/atom/ns#'>debian</category><category domain='http://www.blogger.com/atom/ns#'>bad code</category><category domain='http://www.blogger.com/atom/ns#'>modconf</category><title>Making modconf work with Linux 3</title><description>&lt;p&gt;If you want a nice curses based GUI to add and remove modules from Linux on the fly, you probably used modconf. They say it's deprecated, but they still haven't made anything to replace it.&lt;/p&gt;&lt;p&gt;I noticed that it stopped working on Linux 3.&lt;/p&gt;&lt;p&gt;The problem is as follows, the configuration scripts that come with modconf generally look to see if you're using Linux 2.0 - 2.4 and do one thing, and do another for 2.5 and up. They generally check just the second digit, so now with Linux "3.0" it thinks you're using 2.0 and does something for &amp;lt;2.5 when it should be using the &amp;gt;=2.5 method.&lt;/p&gt;&lt;p&gt;Edit &lt;i&gt;/usr/share/modconf/params&lt;/i&gt;&lt;br /&gt;Look for:&lt;br /&gt;&lt;pre&gt;case "$(uname -r | cut -f2 -d.)" in&lt;br /&gt;  0|1|2|3|4)&lt;br /&gt;  CFGFILE=$Target/etc/modules.conf&lt;br /&gt;  MODUTILSDIR=$Target/etc/modutils&lt;br /&gt;  ;;&lt;br /&gt;  *)&lt;br /&gt;  CFGFILE=$Target/etc/modprobe.d&lt;br /&gt;  MODUTILSDIR=$Target/etc/modprobe.d&lt;br /&gt;  ;;&lt;br /&gt;esac&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Replace it with:&lt;br /&gt;&lt;pre&gt;CFGFILE=$Target/etc/modprobe.d&lt;br /&gt;MODUTILSDIR=$Target/etc/modprobe.d&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;Edit &lt;i&gt;/usr/share/modconf/util&lt;/i&gt;&lt;br /&gt;Look for:&lt;br /&gt;&lt;pre&gt;  case "$(uname -r | cut -f2 -d.)" in&lt;br /&gt;     0|1|2|3|4)&lt;br /&gt;     modsuffix=".o"&lt;br /&gt;     using_mit=1&lt;br /&gt;     ;;&lt;br /&gt;     *)  modsuffix=".ko" ;;&lt;br /&gt;  esac&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Replace it with:&lt;br /&gt;&lt;pre&gt;modsuffix=".ko"&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;And that's all there is to it!&lt;/p&gt;</description><link>http://insanecoding.blogspot.com/2011/11/making-modconf-work-with-linux-3.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-4360871671430803612</guid><pubDate>Wed, 26 Oct 2011 01:24:00 +0000</pubDate><atom:updated>2013-03-18T13:27:20.249-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>good code</category><category domain='http://www.blogger.com/atom/ns#'>Ancient Coding Ideas</category><category domain='http://www.blogger.com/atom/ns#'>insane ideas</category><category domain='http://www.blogger.com/atom/ns#'>language</category><title>A stronger C/C++ Preprocessor</title><description>Ever felt you needed some preprocessing to generate some C/C++ code for you, but the C preprocesssor is too lacking? Say for example you wanted to include &lt;b&gt;part&lt;/b&gt; of another file, or include output from an application. Perhaps the compile should be based on some data found on a remote server? Well, there are stronger preprocessors which work for C/C++, such as PHP.&lt;br /&gt;&lt;br /&gt;Here's an example:&lt;br /&gt;&lt;pre&gt;/tmp&amp;gt; php test.cpp.php | g++ -x c++ -Wall -o test -&lt;br /&gt;/tmp&amp;gt; ./test&lt;br /&gt;Hello 0&lt;br /&gt;Hello 1&lt;br /&gt;Hello 2&lt;br /&gt;Hello 3&lt;br /&gt;Hello 4&lt;br /&gt;/tmp&amp;gt; cat test.cpp.php&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;  &amp;lt;?php for ($i = 0; $i &lt; 5; ++$i) { echo 'std::cout &amp;lt;&amp;lt; "Hello ', $i, '" &amp;lt;&amp;lt; std::endl;'; } ?&amp;gt;&lt;br /&gt;  return(0);&lt;br /&gt;}&lt;br /&gt;/tmp&amp;gt;&lt;/pre&gt;Here's a more interesting example:&lt;br /&gt;&lt;pre&gt;/tmp&amp;gt; php weather_example.c.php | gcc -x c -Wall -o weather_example -&lt;br /&gt;/tmp&amp;gt; ./weather_example&lt;br /&gt;Hi, when I was compiled, the weather here in New York City was 57F&lt;br /&gt;/tmp&amp;gt; cat weather_example.c.php&lt;br /&gt;&amp;lt;?php&lt;br /&gt;$w = file_get_contents('http://www.google.com/ig/api?weather=New+York+City');&lt;br /&gt;$f = '&amp;lt;temp_f data="';&lt;br /&gt;echo '#define __WEATHER__ ', (int)substr($w, strpos($w, $f)+strlen($f)), 'U', "\n";&lt;br /&gt;?&amp;gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;  printf("Hi, when I was compiled, the weather here in New York City was %uF\n", __WEATHER__);&lt;br /&gt;  return(0);&lt;br /&gt;}&lt;br /&gt;/tmp&amp;gt;&lt;/pre&gt;</description><link>http://insanecoding.blogspot.com/2011/10/stronger-cc-preprocesser.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-6885910511143196800</guid><pubDate>Sun, 16 Oct 2011 13:26:00 +0000</pubDate><atom:updated>2011-10-16T06:38:46.531-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>code search</category><category domain='http://www.blogger.com/atom/ns#'>pure failure</category><category domain='http://www.blogger.com/atom/ns#'>API</category><category domain='http://www.blogger.com/atom/ns#'>searching</category><category domain='http://www.blogger.com/atom/ns#'>Google</category><category domain='http://www.blogger.com/atom/ns#'>Optimization</category><title>Goodbye Google</title><description>Google &lt;a href="http://googleblog.blogspot.com/2011/10/fall-sweep.html"&gt;announced&lt;/a&gt; they're shutting down &lt;a href="http://www.google.com/codesearch"&gt;Code Search&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I found Google Code Search to be invaluable in the kind of work I do. I saved tons of time by being able to find existing code for something tricky already invented. Or I could compare multiple implementations for things to learn about what different techniques there are for various operations and learn immensely from their pros and cons. If you're reimplementing something yourself, it's also nice to be easily able to find tests cases and other things with Google Code Search.&lt;br /&gt;&lt;br /&gt;Now all that is going away. Are there any feasible alternatives? Do we need to start a competing search engine? What are programmers to do when Google cuts the number one online tool for researching code?</description><link>http://insanecoding.blogspot.com/2011/10/goodbye-google.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>7</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-2767580020236296293</guid><pubDate>Mon, 20 Jun 2011 13:33:00 +0000</pubDate><atom:updated>2011-06-20T06:39:12.801-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>non rectangular array</category><category domain='http://www.blogger.com/atom/ns#'>C++ 2011</category><category domain='http://www.blogger.com/atom/ns#'>GCC</category><category domain='http://www.blogger.com/atom/ns#'>initializer lists</category><title>C++ 2011 and non rectangular arrays</title><description>Ever wanted to make a non rectangular array? Meaning for example, some multidimensional array where a[0] has 3 members and a[1] has 5 members, and so on.&lt;br /&gt;&lt;br /&gt;You could do it with first building up the outermost array, and then add on each subarray separately, but you can't do it all in one shot at initialization time.&lt;br /&gt;&lt;br /&gt;But enter C++ 2011 with initializer lists. You can initialize vectors of vectors with as many members at each level you want.&lt;br /&gt;&lt;br /&gt;This works:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; a&lt;br /&gt;(&lt;br /&gt;  {&lt;br /&gt;    { 1, },&lt;br /&gt;    { 1, 2, },&lt;br /&gt;    { 1, 2, 3, },&lt;br /&gt;    { 1, 2, 3, 4, 5, 6, 7, },&lt;br /&gt;    { 1, 2, },&lt;br /&gt;  }&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;a.size() is 5, a[0].size() is 1, a[1].size() is 2, and so on.&lt;br /&gt;&lt;br /&gt;Here's a complete example:&lt;br /&gt;&lt;pre style="background-color: #F5F2D5"&gt;&lt;span style="color: #008000;"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;#include &amp;lt;vector&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt; std;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;vector&amp;lt;vector&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&amp;gt; a&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    { &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;, },&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    { &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;, },&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    { &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;, },&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    { &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;4&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;5&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;6&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;7&lt;/span&gt;&lt;span style="color: #000000;"&gt;, },&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    { &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;, },&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; print(&lt;/span&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; t)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  cout &amp;lt;&amp;lt; t &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #dd0000;"&gt;", "&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;template&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;typename&lt;/span&gt;&lt;span style="color: #000000;"&gt; T&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; print(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; T &amp;amp;t)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #800000;"&gt;auto&lt;/span&gt;&lt;span style="color: #000000;"&gt; i = t.begin(); i != t.end(); ++i)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    print(*i);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  cout &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;'\n'&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; main()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  print(a);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/tmp&amp;gt; g++-4.4 -Wall -o test test.cpp -std=c++0x&lt;br /&gt;/tmp&amp;gt; ./test&lt;br /&gt;1,&lt;br /&gt;1, 2,&lt;br /&gt;1, 2, 3,&lt;br /&gt;1, 2, 3, 4, 5, 6, 7,&lt;br /&gt;1, 2,&lt;br /&gt;&lt;br /&gt;/tmp&amp;gt;&lt;br /&gt;&lt;/pre&gt;</description><link>http://insanecoding.blogspot.com/2011/06/c-2011-and-non-rectangular-arrays.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-8043809126962101793</guid><pubDate>Mon, 20 Jun 2011 12:22:00 +0000</pubDate><atom:updated>2011-06-20T05:30:57.656-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>C++ 2011</category><category domain='http://www.blogger.com/atom/ns#'>GCC</category><category domain='http://www.blogger.com/atom/ns#'>lambda functions</category><category domain='http://www.blogger.com/atom/ns#'>c99</category><category domain='http://www.blogger.com/atom/ns#'>__func__</category><title>C++ 2011 and __func__</title><description>So what happens to __func__ in different scopes? How about GCC's extension for pretty function names?&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color:#F5F2D5;"&gt;&lt;span style="color: #008000;"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt; std;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;namespace&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="color: #800000;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; f()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #800000;"&gt;auto&lt;/span&gt;&lt;span style="color: #000000;"&gt; func = []()-&amp;gt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *{ &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;(__func__); };&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #800000;"&gt;auto&lt;/span&gt;&lt;span style="color: #000000;"&gt; func2 = []()-&amp;gt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *{ &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;(__PRETTY_FUNCTION__); }; &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//GCC extension&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    cout &amp;lt;&amp;lt; func() &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;'\n'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;         &amp;lt;&amp;lt; func2() &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;'\n'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;         &amp;lt;&amp;lt; __func__ &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;'\n'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;         &amp;lt;&amp;lt; __PRETTY_FUNCTION__ &amp;lt;&amp;lt; endl;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; main()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  f();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  cout &amp;lt;&amp;lt; __func__ &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;'\n'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;       &amp;lt;&amp;lt; __PRETTY_FUNCTION__ &amp;lt;&amp;lt; endl;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/tmp&amp;gt; g++-4.5 -Wall -o test test.cpp -std=c++0x&lt;br /&gt;/tmp&amp;gt; ./test&lt;br /&gt;operator()&lt;br /&gt;&amp;lt;unnamed&gt;::f()::&amp;lt;lambda()&amp;gt;&lt;br /&gt;f&lt;br /&gt;void&amp;lt;unnamed&amp;gt;::f()&lt;br /&gt;main&lt;br /&gt;int main()&lt;br /&gt;/tmp&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;&lt;br /&gt;/tmp&amp;gt; g++-4.6 -Wall -o test test.cpp -std=c++0x&lt;br /&gt;/tmp&amp;gt; ./test&lt;br /&gt;operator()&lt;br /&gt;{anonymous}::f()::&amp;lt;lambda()&amp;gt;&lt;br /&gt;f&lt;br /&gt;void {anonymous}::f()&lt;br /&gt;main&lt;br /&gt;int main()&lt;br /&gt;/tmp&amp;gt;&lt;br /&gt;&lt;/pre&gt;</description><link>http://insanecoding.blogspot.com/2011/06/c-2011-and-func.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-6666768773740268340</guid><pubDate>Sat, 09 Apr 2011 18:41:00 +0000</pubDate><atom:updated>2011-04-09T15:33:40.976-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>bugs</category><category domain='http://www.blogger.com/atom/ns#'>signed</category><category domain='http://www.blogger.com/atom/ns#'>pure failure</category><category domain='http://www.blogger.com/atom/ns#'>Mozilla</category><category domain='http://www.blogger.com/atom/ns#'>compatibility</category><category domain='http://www.blogger.com/atom/ns#'>secure</category><category domain='http://www.blogger.com/atom/ns#'>Google</category><category domain='http://www.blogger.com/atom/ns#'>Portability</category><category domain='http://www.blogger.com/atom/ns#'>protocols</category><title>The failure of fragmented security</title><description>With recent attacks against &lt;a href="http://en.wikipedia.org/wiki/Transport_Layer_Security"&gt;SSL/TLS&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Public_key_certificate"&gt;certificates&lt;/a&gt;, everyone has been thinking a lot about security. What can we do to prevent security problems in the future?&lt;br /&gt;&lt;br /&gt;The problem really stems from the fact that our different security components are separate from one another, and don't entirely see eye to eye, leaving gaps for attackers to walk right on through. The current certificate system for certifying the identity of a website is flawed in theory, and in its implementation in many browsers.&lt;br /&gt;&lt;br /&gt;The current system works as follows: An entity submits proof of ownership of the domain(s) it owns to one of hundreds of &lt;a href="http://en.wikipedia.org/wiki/Certificate_authority"&gt;certificate authorities&lt;/a&gt; out there, who follow some kind of verification process, and then proceed to give a certificate identifying the site to that entity. This certificate is digitally signed by the certificate authority itself using their private unknown keys. Since no one but the certificate authority itself has their private keys, they're the only ones able to sign certificates in their own name. Browsers ship with a certificate bundle identifying the certificate authorities they trust. In this way, when you see a site with a certificate signed by a known certificate authority, you know it's the site you intended to visit.&lt;br /&gt;&lt;br /&gt;Except there's some flaws with this idea. If terrorists wanted to, they could attack a certificate authority's physical headquarters and steal their private keys from their server and sign whatever they want for whichever domain they wish. Or, hackers could hack into machines remotely and perhaps get lucky and find some private keys on them. Or, anyone could start their own certificate authority. It really isn't that hard. Once your new authority becomes trusted by the various browsers, you can proceed to generate certificates for any domain desired.&lt;br /&gt;&lt;br /&gt;This entire system has multiple points of failure. Further compounding the issue is that several "trusted" certificate authorities also are in themselves ISPs or run various links in the vast internet. Having both components in your control allow you to impersonate any site for any information passing through your systems. America Online for example is both a trusted certificate authority and an ISP, and anyone who works there and has access to their infrastructure and private keys can view all HTTPS encrypted data passing through their network as unencrypted. Want to buy something with your credit card online? You might want to &lt;a href="http://en.wikipedia.org/wiki/Traceroute"&gt;traceroute&lt;/a&gt; your connection first and ensure no one along the way is also a certificate authority your browser trusts.&lt;br /&gt;&lt;br /&gt;In order to mitigate a certificate authority signing something it shouldn't have, they invented &lt;a href="http://en.wikipedia.org/wiki/Revocation_list"&gt;Certificate Revocation Lists&lt;/a&gt;. Where an authority can revoke specific certificates it once signed, since every certificate also has an ID number associated with it. But, some browsers don't even bother checking these lists. Further, some browsers which make use of CRLs and their friends, resume as if nothing happened if they couldn't access a CRL for some reason. Further, these CRLs are subject to the same security problems just described for domains in general. How do I know this is indeed the real CRL? Also, browsers themselves don't have CRLs for the root certificates they ship with, so they are unable to revoke a certificate of a rogue CA if they need to.&lt;br /&gt;&lt;br /&gt;But in reality, this entire system is flawed from the ground up. It's so flawed, it doesn't even make the slightest bit of sense. Imagine the following scenario where my boss asks me to inform him of all purchasing details for our web presence needs, and explain why they're needed.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&amp;lt;Me&amp;gt; Okay, we're going to need $35 a year to &lt;a href="http://en.wikipedia.org/wiki/Domain_registry"&gt;register all the domains&lt;/a&gt; we want for our company, such as company.com and company.net and so on.&lt;br /&gt;&amp;lt;Him&amp;gt; Sure, that's fine, what else?&lt;br /&gt;&amp;lt;Me&amp;gt; Then we're going to need $200 a year for each domain for certificates.&lt;br /&gt;&amp;lt;Him&amp;gt; Why do we need these certificates?&lt;br /&gt;&amp;lt;Me&amp;gt; To prove that we own the domain in question.&lt;br /&gt;&amp;lt;Him&amp;gt; Prove it? Why?&lt;br /&gt;&amp;lt;Me&amp;gt; Browsers like Internet Explorer and Firefox won't realize when they visit our domain that its really our domain, and not some hacker out there trying to impersonate us.&lt;br /&gt;&amp;lt;Him&amp;gt; So if we don't buy these certificates, hackers will be able to get the domain names registered as their own instead of ours?&lt;br /&gt;&amp;lt;Me&amp;gt; No, the domain names are protected by a central authority, they know that we own them, and we tell them to point the domains at our servers, but hackers in between our customer's browser and our server can hijack the connection and make believe they're us without a certificate.&lt;br /&gt;&amp;lt;Him&amp;gt; I don't get it, why can't our customer's browser just check the domain registry and make sure the server they reach is the one we told the domain registry about? Why do we need to buy something from a 3rd party?&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This seems strange to you? He's absolutely right. Why can't the &lt;a href="http://en.wikipedia.org/wiki/Root_nameserver"&gt;hierarchy&lt;/a&gt; for domain management also distribute the public keys for our servers? The systems will need to be modified to combine several components and have encryption at each level, but does anything else make an ounce of sense?&lt;br /&gt;&lt;br /&gt;Imagine you wanted to buy some property. You have your lawyer, accountant, realtor, and other people directly related to the purchase. After everything is taken care of, and you submit forms to city hall and everything else, you then go down to Joe's House of Fine Refrigerators and have him give you a signed deed that you indeed own the property in question. Makes a lot of sense, right?&lt;br /&gt;&lt;br /&gt;Now you call a construction company down to work on your new property, say to merge it with the property next door to it. They want proof you own both properties before beginning. What do you do? You pull out your deed from Joe's House of Fine Refrigerators.&lt;br /&gt;&lt;br /&gt;This is the exact state of internet security today. This problem is even pervasive down to every level of infrastructure we use.&lt;br /&gt;&lt;br /&gt;Take &lt;a href="http://en.wikipedia.org/wiki/HTTP_cookie"&gt;cookies&lt;/a&gt; for example, the system it uses to match domain names runs completely counter to how the &lt;a href="http://en.wikipedia.org/wiki/Domain_Name_System"&gt;domain name system&lt;/a&gt; works. It's actually impossible for any browser to properly know for every set of domains in existence whether they're paired or not when it comes to handling cookies for them. It will either fail to submit cookies to some sites that it should, or submit cookies to some sites it shouldn't. Some browsers try to solve this problem with a massive hack, a &lt;a href="http://publicsuffix.org/"&gt;list of domains that cookies should know are or aren't paired together&lt;/a&gt;, which is also incomplete, and needs never ending updates. Without the list, the only difference is that the browser is just wrong more often than without it.&lt;br /&gt;&lt;br /&gt;Really, &lt;a href="http://insanecoding.blogspot.com/2009/11/malicious-hackers-are-not-out-there.html"&gt;if the hackers were out there&lt;/a&gt;, we'd be in big trouble.</description><link>http://insanecoding.blogspot.com/2011/04/failure-of-fragmented-security.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-8474574769803680321</guid><pubDate>Thu, 25 Nov 2010 22:51:00 +0000</pubDate><atom:updated>2010-11-26T02:34:24.177-08:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>good code</category><category domain='http://www.blogger.com/atom/ns#'>recursion</category><category domain='http://www.blogger.com/atom/ns#'>compatibility</category><category domain='http://www.blogger.com/atom/ns#'>Library</category><category domain='http://www.blogger.com/atom/ns#'>GCC</category><category domain='http://www.blogger.com/atom/ns#'>insane ideas</category><category domain='http://www.blogger.com/atom/ns#'>C++-201x</category><category domain='http://www.blogger.com/atom/ns#'>variadic templates</category><category domain='http://www.blogger.com/atom/ns#'>C++-0x</category><category domain='http://www.blogger.com/atom/ns#'>Portability</category><category domain='http://www.blogger.com/atom/ns#'>language</category><category domain='http://www.blogger.com/atom/ns#'>protocols</category><title>C++ Serialization Anyone?</title><description>Today I had one of the most amazing programming experiences that I've ever had, from my entire exciting career. I'm still a bit stunned that this happened. I fully thought what happened was completely impossible till now.&lt;br /&gt;&lt;br /&gt;At work, we use a lot of different languages to create our software. It's not odd for us to be working on a project which somehow ends up using a dozen languages. Between server code, client code, databases, communication, mark up, styling, pre-processing, dynamic code generation, and other commonality, it's rather easy actually.&lt;br /&gt;&lt;br /&gt;Between all these different programming languages, quite often, we need some sort of data interchange format. There's many to choose from, ranging from something custom to something well known like XML. Using these formats, we can pass data from one segment of our application stack to another. Even when they use two different programming languages. Or to save some data, and load it back up later.&lt;br /&gt;&lt;br /&gt;When it comes to these things, soft typed functional languages are generally easier to work with than hard typed. Soft typed languages are very good at building objects from data on the fly, thanks to their ability to not care much about what types they're looking at. Is it a number or a string? Doesn't matter to the soft typed language, as they store it all the same way.&lt;br /&gt;&lt;br /&gt;When dealing with database access from hard typed languages, the popular method is to create some sort of catch all or convert to &lt;i&gt;anything&lt;/i&gt; type. For some, terms like "QVariant" or "boost::any" are always on their lips. The intent of these and similar constructs is to ease things when dealing with data in an unknown type. Although such constructs generally require building a switch block which needs to check some enumeration method to figure out how to handle the data within the rest of the program. Such code is just downright annoying.&lt;br /&gt;&lt;br /&gt;At work some time back, thanks to a lot of the new features C++-201x has been adding, we've been able to build a database access library which can handle data without any of these old kludges. Essentially, database access for us in C++ is now just as easy as it is in PHP (or perhaps even easier!).&lt;br /&gt;&lt;br /&gt;Now database communication is great, but there's still the issue of data interchange between two programs, which aren't using a database as an intermediary. Many soft typed or functional languages can have a simple encode() or decode() function, pass it any object, and have a nice string representation of it which can be sent off, or saved to a file for later. C++ and related languages always had the nightmare of needing to iterate manually over every data type, or over a hierarchy to work with something like XML, or similar data formats.&lt;br /&gt;&lt;br /&gt;There's those that have created workarounds of course. Such as adding a serialize() function for every type you have to work with individually. Or create some serializable objects that one copies data to or from, and which handle all the serialization work internally. Or one of my personal favorites, write a separate parser which can read a description of a format, and generate the C++ objects and code needed to serialize or deserialize it.&lt;br /&gt;&lt;br /&gt;Well, today a coworker and I were putting our heads together on how to deal with a certain project. I wrote code some time back which can serialize/deserialize to and from an std::map which contains numbers, strings, or a mix thereof. We were using this data interchange format between two programs. However, now we need to deal with much more complex data, and a series of key pairs just won't cover it. One end of the equation is C++, the other end is a soft typed language which could pretty easily work with whatever we came up with.&lt;br /&gt;&lt;br /&gt;We first thought about the option of using a classic method such as XML or JSON, and use some kind of hierarchical writer from C++, and have the soft typed language just read it directly into an object with one of its built in language features. Till my friend had a brilliant realization. The hierarchy of language containers and their children is &lt;b&gt;recursive&lt;/b&gt;, as is any serialization that can encode an infinite amount of data stacked in a hierarchy. Then we started discussing if we could make a serialize() function in C++ which could take any C++ type and work, even when not knowing everything about it in advance. It'd be easy for plain old data types, but gets more complicated once we start dealing with containers of those, and containers of containers.&lt;br /&gt;&lt;br /&gt;Of course this is where most conversations along these lines end. But then I brought up template meta programming, and some new features C++ is now adding (and already in GCC), and this discussion went on much further than usual, till the point we were talking code. Well, we got into it, and two hours and two hundred lines of code later, we now have a function with the following prototype:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;template&amp;lt;typename T&amp;gt;&lt;br /&gt;std::string serialize(const T &amp;amp;t);&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;It is able to take any type that exists in C++, and well, serialize it. Have some type which contains some types which contains a few more types which contains some other types? It's all serializeable with this function. No pre-processing, dynamic code generation, compiler hacks, or clumsy per program hierarchical parsing required. It just works&lt;sup&gt;TM&lt;/sup&gt;.&lt;br /&gt;&lt;br /&gt;Now next week, we'll have to write the deserializer function to pull that magic in reverse. Using the same idea, it shouldn't be a problem. If the data matches the supplied structure, parse it in, otherwise, throw an error. But currently, our project is done, as we are now able to have our C++ applications send very complex data to our soft typed languages rather easily.&lt;br /&gt;&lt;br /&gt;Looking over the code with my coworker, it all seems extremely obvious. Why the heck didn't we think of this 20 years ago? Now am I getting all excited over something that has been done before? Anyone familiar with anything like this?&lt;br /&gt;&lt;br /&gt;Question is, what to do now that we know this? File for a patent? (Yes, I'm evil!) Or perhaps ignore this, as no one cares about this topic anyway?</description><link>http://insanecoding.blogspot.com/2010/11/c-serialization-anyone.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>14</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-2620795255299236918</guid><pubDate>Sat, 30 Oct 2010 23:29:00 +0000</pubDate><atom:updated>2010-10-31T00:58:09.510-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>crazy executives</category><category domain='http://www.blogger.com/atom/ns#'>Mozilla</category><category domain='http://www.blogger.com/atom/ns#'>distribution</category><category domain='http://www.blogger.com/atom/ns#'>Windows</category><category domain='http://www.blogger.com/atom/ns#'>competition</category><category domain='http://www.blogger.com/atom/ns#'>KDE</category><category domain='http://www.blogger.com/atom/ns#'>open source</category><category domain='http://www.blogger.com/atom/ns#'>compatibility</category><category domain='http://www.blogger.com/atom/ns#'>pure failure</category><category domain='http://www.blogger.com/atom/ns#'>HTTP</category><category domain='http://www.blogger.com/atom/ns#'>Google</category><category domain='http://www.blogger.com/atom/ns#'>standards compliance</category><category domain='http://www.blogger.com/atom/ns#'>Portability</category><title>This just in, 20% of enterprises and most IT people are idiots</title><description>So, who still runs Internet Explorer 6? I do, because sometimes, I'm a web developer.&lt;br /&gt;Along with IE 6, I also run later versions of IE, as well as Firefox, Opera, Chrome, Safari, Arora, Maxthon, and Konqueror. So do my web developer friends and coworkers.&lt;br /&gt;&lt;br /&gt;The reason why we do is simple. We want to test our products with every browser with any sort of popularity. Or is a browser that comes with some sort of OS or environment with any sort of popularity. Same goes for browsers with a specific engine.&lt;br /&gt;&lt;br /&gt;By playing with so many browsers, we get a feel for things which seem to not be well known (even when documented well), or completely missed by the "pros" who write the most noise on the subject at hand. After work, sometimes my coworkers and I like to get together and joke about how Google security researchers put out a security memo on IE, citing no recourse, while the solution is clearly documented on MSDN, or any similar scenario.&lt;br /&gt;&lt;br /&gt;Perhaps we're bad guys for not writing lengthy articles on every subject, and keeping knowledge to ourselves. On the other hand, we get to laugh at the general population on a regular basis. Something which I'm sure every geek at heart revels in.&lt;br /&gt;&lt;br /&gt;Here's a small sampling of popular beliefs that we snicker at:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Internet Explorer 6 can't &lt;a href="http://groopex.com/"&gt;properly display transparent PNGs&lt;/a&gt; without resorting to fancy CSS+JS hacks.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;JavaScript event handling code can't receive the event handle with IE.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Menus are required to be written in JavaScript to work with all browsers.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;IE is unable to &lt;a href="http://msdn.microsoft.com/en-us/library/aa384321%28v=VS.85%29.aspx"&gt;receive multiple cookies in a single Set-Cookie field&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Cookies is the (only) proper way to store HTTP state.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;IE is not the most advanced browser when it comes to text and typography (&lt;a href="http://www.microsoft.com/middleeast/msdn/JustifyingText-CSS.aspx"&gt;because it is, by far&lt;/a&gt;).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;SSL/TLS can never be &lt;a href="http://en.wikipedia.org/wiki/Server_Name_Indication"&gt;used with multiple virtual hosts&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Common examples of how to write proper cross browser code is accurate. (Such as common methods to support embedded fonts for IE and other browsers break Konqueror, when supporting all of them is a piece of cake. Or use embed tags for &lt;a href="http://tasvideos.org/"&gt;flash&lt;/a&gt;.)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;HTTP doesn't have &lt;a href="http://tools.ietf.org/html/rfc2617"&gt;native authentication abilities&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/performance/rules.html#js_bottom"&gt;JavaScript should be included in&lt;/a&gt; HTML head.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.php.net/manual/en/class.pdostatement.php"&gt;SQL query parameters&lt;/a&gt; should be escaped.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Faith in standards committees, large corporations, open source projects, or security researchers.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;That multiple versions of IE can't be run on Windows easily, especially older versions of IE on newer versions of Windows.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;That last one is actually what prompted this article. &lt;a href="http://www.computerworld.com/s/article/9193901/IE6_addiction_throws_monkey_wrench_into_Windows_7_migration"&gt;20% of enterprises say they can't upgrade to newer versions of Windows because they need to use IE 6&lt;/a&gt;. On top of this, almost every IT guy who had anything to say about this believe in this situation or mentions virtualization as an out. Heck, even Microsoft themselves are saying you need a special XP mode in Windows 7 for IE 6, as is every major article site on the net who comment on this situation.&lt;br /&gt;&lt;br /&gt;Hilarious considering that you can &lt;a href="http://utilu.com/IECollection/#table"&gt;install and run IE 6 just fine in Windows 7&lt;/a&gt;. There's plenty of solutions out there besides that one too. They've also been around for several years.&lt;br /&gt;&lt;br /&gt;Anyways, experts, pros, designers, IT staff and average Internet surfers out there, just keep on being clueless on every single topic, some of us are having a real laugh.</description><link>http://insanecoding.blogspot.com/2010/10/this-just-in-20-of-enterprises-and-most.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-6394991886782955885</guid><pubDate>Sun, 24 Oct 2010 13:12:00 +0000</pubDate><atom:updated>2010-10-24T06:52:03.402-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>competition</category><category domain='http://www.blogger.com/atom/ns#'>parameters</category><category domain='http://www.blogger.com/atom/ns#'>CPU Detection</category><category domain='http://www.blogger.com/atom/ns#'>compatibility</category><category domain='http://www.blogger.com/atom/ns#'>BIOS</category><category domain='http://www.blogger.com/atom/ns#'>API</category><category domain='http://www.blogger.com/atom/ns#'>binary</category><category domain='http://www.blogger.com/atom/ns#'>protocols</category><category domain='http://www.blogger.com/atom/ns#'>closed source</category><title>Programming manuals for those who "get it"</title><description>Top secret official programming manuals for certain popular hand held devices have now been uploaded to the &lt;span style="font-style:italic;"&gt;usual&lt;/span&gt; &lt;span style="font-weight:bold;"&gt;public&lt;/span&gt; document repositories. Some have been around for a while to those who &lt;span style="font-style:italic;"&gt;get it&lt;/span&gt;, some are new.</description><link>http://insanecoding.blogspot.com/2010/10/programming-manuals-for-those-who-get.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-8756036999901138643</guid><pubDate>Sun, 19 Sep 2010 11:59:00 +0000</pubDate><atom:updated>2010-09-19T08:03:16.186-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Library</category><category domain='http://www.blogger.com/atom/ns#'>opendir</category><category domain='http://www.blogger.com/atom/ns#'>bad code</category><category domain='http://www.blogger.com/atom/ns#'>readdir</category><category domain='http://www.blogger.com/atom/ns#'>file descriptor</category><category domain='http://www.blogger.com/atom/ns#'>open source</category><category domain='http://www.blogger.com/atom/ns#'>good code</category><category domain='http://www.blogger.com/atom/ns#'>fstatat</category><category domain='http://www.blogger.com/atom/ns#'>torture</category><category domain='http://www.blogger.com/atom/ns#'>directory</category><category domain='http://www.blogger.com/atom/ns#'>searching</category><category domain='http://www.blogger.com/atom/ns#'>sorting</category><category domain='http://www.blogger.com/atom/ns#'>language</category><category domain='http://www.blogger.com/atom/ns#'>Hashing</category><category domain='http://www.blogger.com/atom/ns#'>Optimization</category><title>Optimizing your file dialog</title><description>Recently, someone asked me why is it that the custom file dialogs in some programs I wrote are able to load a file list so much faster than the so called "native file dialogs" on those operating systems. The answer is that I optimized many areas of loading a file list, and displaying it. Today we'll look at some optimizations that can be performed, instead of using the most obvious approaches to most of the process.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;h4&gt;Know your system calls for reading directory entries&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;You'll want to create some sort of library around the native directory functions in order to use the most efficient path on each operating system. Operating systems vary widely in what they they provide.&lt;br /&gt;&lt;br /&gt;Sometimes you have multiple APIs, or a single API with many options you can turn on and off. Unless the provided API is in itself doing everything as efficiently as possible (such as efficiently returning the file names in a sorted matter), you'll want to use the lowest level API, or turn off all options it provides.&lt;br /&gt;&lt;br /&gt;If bidirectional or scanning options are provided, turn them off, as you'll want forward only. The overhead for some of these features can significantly slow down the process of obtaining a file list. Same goes for anything else that adds overhead.&lt;br /&gt;&lt;br /&gt;Be aware of what information is provided other than file names. Some OSs will return a structure which may also contain file size or file permissions alongside each file. If you're filtering by any of these, use the information directly there, instead of using an additional call to stat() or similar.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In addition to the above, if you need to filter by file size or file permissions, and the API does not provide that information directly, avoid the need for concatenating strings to get your information. A call to stat() would require concatenating a file name onto the directory name if it's not in the current directory. If your OS provides for it, use fstatat() or similar instead (see "OpenGroup Extended API Set Part 2").&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;h4&gt;Process file names in an optimized manner&lt;/h4&gt;&lt;br /&gt;Once you start getting back file name(s), before anything, determine the length of a file name, as all other operations will need to know the length. Pretty much every operating system / file system limits the length of a file name to 255 bytes, the length of that can fit in a single byte. Compute the length (if need be) and keep reusing this cache.&lt;br /&gt;&lt;br /&gt;If you want to do extension filtering, now is the time to do so. Do not use strrchr(),  or anything of the sort to find where the extension begins (searching for a period). Functions like strrchr() will first travel to the end then look back, effectively being O(2N). Since you already know the length of the string, use an O(N) function to look back from the end. Perhaps even using one which can scan multiple bytes (whole CPU words) at a time.&lt;br /&gt;&lt;br /&gt;For extension filtering, the most common method is generally one that breaks down to a series of compares. Put a little more thought into your algorithm usage! Either sort your list of extensions and &lt;a href="http://en.wikipedia.org/wiki/Binary_search_algorithm"&gt;binary search&lt;/a&gt; it for a match, or use &lt;a href="http://en.wikipedia.org/wiki/Perfect_hash_function"&gt;perfect hashing&lt;/a&gt;. In either case, make sure the sorting or hashing phase is performed just once.&lt;br /&gt;&lt;br /&gt;For copying the files names you want elsewhere, use memcpy() instead of strcpy() and similar. Don't forget to pass around the length for other uses too.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;h4&gt;Use efficient data structures efficiently&lt;/h4&gt;&lt;br /&gt;The next question is how to keep track of your list of files. The most two common ideas are to use a vector and just keep adding to it, or use a linked list. Both those solutions are wrong.&lt;br /&gt;&lt;br /&gt;A vector while great in theory, has some performance and memory issues. When a vector can no longer contain what is being added to it, it doubles in size. The doubling in size can cause up to 99% more allocation than is actually needed during the growing process, which also comes with a lot of copying around. This may suit many workloads, but won't always suit the file list workload well.&lt;br /&gt;&lt;br /&gt;A linked list on the other hand is one of the worst possible data structures you can use. Every entry has 100-200% extra overhead for pointers, and often means many series of allocations. Many small allocations leads to performance issues, and a lot of memory fragmentation.&lt;br /&gt;&lt;br /&gt;The solution I would recommend is either a tweaked vector, or a combination of a vector plus linked list. Tweaking a vector starts off with reserving a set amount of space up front. Have your vector by default start with room for say 512 entries, and only then grow as needed. When you see your vector is full, instead of doubling in size, reserve another 512 entries. Smaller requests are more likely to be fulfilled for a realloc() in the same location, than a doubling in size. Very large directories beyond this point also becomes increasingly rarer at each new milestone. On top of all this, have your program remember how many files were in each of the past 10 or so directories it looked in (with filtering options of course). Then when loading a directory you recently loaded in the past, you can allocate an amount which is usually just what you need, or only needs one more chunk allocated onto it. Keep in mind that most users will keep using the same few directories over and over again with each application.&lt;br /&gt;&lt;br /&gt;The combination of the vector and linked list would instead build a structure out of the two ideas combined. Create your array of 512 entries, along with a fill pointer and and linked list pointers. When your array is full, allocate another block of this structure as the next chain in the linked list. This ensures no need to ever reallocate, or copy data around during the growing phase. Of course keep a global pointer to the current link being filled, instead of iterating to it each time you add a new entry.&lt;br /&gt;&lt;br /&gt;Which of these two options you use depends on how you want to sort and display your files. Each data structure has pros and cons for different use cases. Before we get into that, know how to store your file names themselves.&lt;br /&gt;&lt;br /&gt;The above description was for the pointers to the arrays holding the file names, the file names should NOT have a separate block of allocated memory for each. That's inefficient. Instead allocate large chunks of memory, say 16KB each. Store your file names in this &lt;a href="http://en.wikipedia.org/wiki/Memory_pool"&gt;memory pool&lt;/a&gt;. Forget the silly trailing null if you can, store the length before the name itself. The two data structures explained above for containing lists of files will point into these pools. If a pool can't contain another entry you're about to add, allocate another 16KB chunk, point to it from the previous one, and start allocating in this new one. If the need for a new one was for a rare overly large file, say 230 bytes, when 200 bytes were free, you can implement an algorithm to save some overhead by seeing if the next couple of files fit into the end of any previous pools. The pools in general will probably waste less than your OSs malloc() for small file names, and you'll certainly get better performance. Deallocation will also be a quick (backwards) traversal for large chunks instead of many small ones.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;h4&gt;Sort efficiently&lt;/h4&gt;&lt;br /&gt;The first part of sorting is comparison. strcmp()/strncmp() is not the function to use. You want something based on memcmp() as that works faster thanks to having the length of the file name already cached. Of course that's only if you want standard sorting.&lt;br /&gt;&lt;br /&gt;If you want case insensitive sorting, other methods will have to be used. If you're only dealing with ASCII file names, and you're not worried about file names containing control characters or some symbols end up being of equal value, you can compare 4 bytes at a time or'ing each with 0x20202020 (0x2020202020202020 for 8 bytes at a time). You're probably out of luck otherwise for case insensitive, unless someone knows of any good tricks to use.&lt;br /&gt;&lt;br /&gt;If you need "natural sorting", where numbers are compared to each other, so file1 precedes file15, and file2 follows file1 not file15, there's a few implementations floating around online and most are just copies of one another. Sadly, the most popular one I see, which is present in two operating systems, and the native implementation in a particular programming language, happens to incorrectly handle numbers past a certain magnitude (did anyone even test the implementations or just accept them at face value?), and has a worse case of O(3N). So beware of what you use or base your code off of.&lt;br /&gt;&lt;br /&gt;I'd recommend something along these lines:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5;"&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; strnatbase(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *s1, &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *s2)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt; (; *s1; ++s1, ++s2) &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//No need to check s2, as we compare it to s1, and it won't equal if it's null&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (isdigit(*s1) &amp;amp;&amp;amp; isdigit(*s2)) &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//If they're both digits, use this special handling&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt; (*s1 == &lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;'0'&lt;/span&gt;&lt;span style="color: #000000;"&gt;) { ++s1; } &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt; (*s2 == &lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;'0'&lt;/span&gt;&lt;span style="color: #000000;"&gt;) { ++s2; } &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//First skip leading zeros&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="color: #800000;"&gt;register&lt;/span&gt;&lt;span style="color: #000000;"&gt; bool d1 = isdigit(*s1), d2 = isdigit(*s2); &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Are we still in a run of digits for both strings?&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (d1 != d2) { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;(d1-d2); } &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//If for only one of them, return that as the difference&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt; (; d1 &amp;amp;&amp;amp; (*s1 == *s2); ++s2) { d1 = isdigit(*++s1); } &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Keep going while we have matching digits&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      d2 = isdigit(*s2); &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//If we broke the above loop because a single string ran out of digits&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (d1 != d2) { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;(d1-d2); } &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Return that as the difference&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *p1 = s1, *p2 = s2; d1; ) &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Otherwise, difference in the digits themselves, clarify magnitude&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;        d1 = isdigit(*++p1); d2 = isdigit(*++p2); &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//First string to run out of digits first&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (d1 != d2) { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;(d1-d2); } &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Will lose right here&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      } &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//If loop breaks, both strings are out of digits, the difference found above will be handled below&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (NOT_EQUAL(*s1, *s2)) { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;; } &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//In all other cases, fall through with difference in current position - if any&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;(*s1-*s2);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Modify as necessary for unicode, and replace NOT_EQUAL() with your function (or macro) of choice for comparing two letters (accounting for case differences if you want).&lt;br /&gt;&lt;br /&gt;As for the sort functions themselves, it will depend on which data structure you chose. You'll probably want &lt;a href="http://en.wikipedia.org/wiki/Quicksort"&gt;Quicksort&lt;/a&gt; for the vector. Make sure your Quicksort sorts the pointers to the data and not the data itself! Same for any sorting algorithm sorting this. Swapping pointers is quick and easy. For the latter structure, you might want &lt;a href="http://en.wikipedia.org/wiki/Merge_sort"&gt;Merge sort&lt;/a&gt;, or perhaps &lt;a href="http://en.wikipedia.org/wiki/Smoothsort"&gt;Smoothsort&lt;/a&gt;. What you choose can depend on several factors.&lt;br /&gt;&lt;br /&gt;You may or may not want to utilize threading. Depending on how you filter, the OS may be giving you mostly sorted file names which can also play a role in the algorithm you choose. In the case of the linked lists of arrays, you might want to sort each array with one algorithm, then sort the whole. If you're utilizing threading, you can begin sorting the array(s) as you're still obtaining files from the operating system, as disk reads are slower than memory reads (when the current directory contents is not (yet) cached by the OS).&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;h4&gt;Display directly&lt;/h4&gt;&lt;br /&gt;This point is rather simple. Have your file dialog display entries directly from whichever data structure you chose, without copying anything around. Know that most existing file dialog routines provided by various libraries will not be compatible with the data structures described above. So roll your own, or choose structures which can be passed directly to your library.&lt;br /&gt;&lt;br /&gt;Another possibility is to copy entries as they fit in the dialog window. The dialog is unable to show an infinite amount of entries at once, so convert from your structure to its structure just for the current files being viewed. Update as scrolling is performed.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;h4&gt;Search efficiently&lt;/h4&gt;&lt;br /&gt;Many file dialogs provide the option to type in some characters, and the file dialog jumps to the first file that begins with those characters. Since your file dialog is sorted, use binary search. Some people don't realize this, but binary search can find more than just an exact match, binary search can also be used to find the transition from entries "less than" to "first equal match" (in other words, binary search can also be used to find the transition between entries before the first match and the first match itself). Use this to find the first matching file in O(log(N)).&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;This basically wraps up this discussion on how to optimize file dialogs. I once was annoyed that loading up a directory with 20,000 files in it on a particular OS with a particular file browser took a good torturesome 20-30 seconds. Now using my own, I can load a directory with 100,000 files in 1-2 seconds on the same setup.&lt;br /&gt;&lt;br /&gt;Thoughts, improvements, complaints, and every other kind of comment is welcome. Be sure to comment if you take of these ideas to optimize your library or application. I'd love to hear about it.</description><link>http://insanecoding.blogspot.com/2010/09/optimizing-your-file-dialog.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>4</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-4792719090417915905</guid><pubDate>Sat, 24 Jul 2010 17:53:00 +0000</pubDate><atom:updated>2010-07-25T04:42:08.178-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>good code</category><category domain='http://www.blogger.com/atom/ns#'>parameters</category><category domain='http://www.blogger.com/atom/ns#'>types</category><category domain='http://www.blogger.com/atom/ns#'>Function Pointers</category><category domain='http://www.blogger.com/atom/ns#'>insane ideas</category><category domain='http://www.blogger.com/atom/ns#'>factory</category><category domain='http://www.blogger.com/atom/ns#'>Optimization</category><title>Simplifying bootstrapping for virtual constructors</title><description>Last week I &lt;a href="http://insanecoding.blogspot.com/2010/07/time-to-shutdown-factory-for-code.html"&gt;demonstrated a solution&lt;/a&gt; to the virtual constructor problem. My solution avoids many issues with the factory function solution. Yet it did require some bootstrapping to use.&lt;br /&gt;&lt;br /&gt;The bootstrapping required a new function to be created for every single derived class that needs to be virtualized. When working with many derived classes, this becomes unacceptable. It's bad enough to solve this problem we need to generate a map, should we have to create additional functions as well? Each time a new derived class is added, should I go out of my way with two steps?&lt;br /&gt;&lt;br /&gt;Turns out, making use of templates, we can combine the define and function generation step.&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; compress *compress_zip::construct() { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; compress_zip; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; compress *compress_gzip::construct() { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; compress_gzip; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; compress *compress_7zip::construct() { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; compress_7zip; }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Instead of creating the above, and using it as follows:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;std::map&amp;lt;COMPRESS_TYPES, compress *(*)()&amp;gt; compress_factory;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;compress_factory[COMPRESS_ZIP] = compress_zip::construct;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;compress_factory[COMPRESS_GZIP] = compress_gzip::construct;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;compress_factory[COMPRESS_7ZIP] = compress_7zip::construct;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;First create a single construct template function:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;template&lt;/span&gt;&lt;span style="color: #000000;"&gt; &amp;lt;&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;typename&lt;/span&gt;&lt;span style="color: #000000;"&gt; T&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;compress *compress_construct()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; T;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This has to be done only once.&lt;br /&gt;&lt;br /&gt;Now when adding to the map, we can do the following:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;std::map&amp;lt;COMPRESS_TYPES, compress *(*)()&amp;gt; compress_factory;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;compress_factory[COMPRESS_ZIP] = compress_construct&amp;lt;compress_zip&amp;gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;compress_factory[COMPRESS_GZIP] = compress_construct&amp;lt;compress_gzip&amp;gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;compress_factory[COMPRESS_7ZIP] = compress_construct&amp;lt;compress_7zip&amp;gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If some new type now comes along, simply add it with a single line. A new function will be generated on use by the template, so you no longer have to. Now we have truly managed to map a type directly to an identifier.&lt;br /&gt;&lt;br /&gt;Of course no tutorial would be complete without a self contained example:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;#include &amp;lt;map&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; base&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  std::string n;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  base(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; std::string &amp;amp;n) : n(n) {}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  base() : n(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"base"&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  std::string name() { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;struct&lt;/span&gt;&lt;span style="color: #000000;"&gt; derived : &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; base&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  derived() : base(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"derived"&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;template&lt;/span&gt;&lt;span style="color: #000000;"&gt; &amp;lt;&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;typename&lt;/span&gt;&lt;span style="color: #000000;"&gt; T&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;base *construct()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; T;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; main(&lt;/span&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; argc, &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; *&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; argv)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  std::map&amp;lt;std::string, base *(*)()&amp;gt; factory;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  factory[&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"b"&lt;/span&gt;&lt;span style="color: #000000;"&gt;] = construct&amp;lt;base&amp;gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  factory[&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"d"&lt;/span&gt;&lt;span style="color: #000000;"&gt;] = construct&amp;lt;derived&amp;gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;try&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Instantiate based on run-time variables&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    base *obj = factory.at(argv[&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;])();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Output&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    std::cout &amp;lt;&amp;lt; obj-&amp;gt;name() &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Cleanup&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;delete&lt;/span&gt;&lt;span style="color: #000000;"&gt; obj;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;catch&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; std::exception &amp;amp;e) { std::cout &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Error occured: "&lt;/span&gt;&lt;span style="color: #000000;"&gt; &amp;lt;&amp;lt; e.what() &amp;lt;&amp;lt; std::endl; }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/tmp&amp;gt; g++-4.4 -Wall -o factory_test factory_test.cpp&lt;br /&gt;/tmp&amp;gt; ./factory_test b&lt;br /&gt;base&lt;br /&gt;/tmp&amp;gt; ./factory_test d&lt;br /&gt;derived&lt;br /&gt;/tmp&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now that this problem has been solved nice and neatly. What about solving it for multiple constructors? Also known as the &lt;a href="http://en.wikipedia.org/wiki/Abstract_factory_pattern"&gt;abstract factory&lt;/a&gt; problem. What if each class has multiple constructors, and we want a collection of them mapped to a single identifier? Can we do it without repeating a lot of code over and over?&lt;br /&gt;&lt;br /&gt;With some minor bootstrapping, the answer is again yes! There's multiple solutions to this problem, but the following is what I found to be the nicest at the moment.&lt;br /&gt;&lt;br /&gt;First create a pure virtual class with a function to match each constructor you'd like to virtualize. Each should of course return a base pointer.&lt;br /&gt;&lt;br /&gt;Imagine we had 3 constructors, one taking no parameters, one taking a C string, and another taking a C++ string, we would setup the following:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;struct&lt;/span&gt;&lt;span style="color: #000000;"&gt; construct_interface&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;virtual&lt;/span&gt;&lt;span style="color: #000000;"&gt; base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()() &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; = &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;virtual&lt;/span&gt;&lt;span style="color: #000000;"&gt; base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *) &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; = &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;virtual&lt;/span&gt;&lt;span style="color: #000000;"&gt; base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; std::string &amp;amp;) &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; = &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once we have the interface defined, we'll create a template construct function which implements and returns that interface within a singleton similar to the above construct function:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;template&lt;/span&gt;&lt;span style="color: #000000;"&gt; &amp;lt;&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;typename&lt;/span&gt;&lt;span style="color: #000000;"&gt; T&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; construct_interface *construct()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="color: #800000;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;struct&lt;/span&gt;&lt;span style="color: #000000;"&gt; : &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; construct_interface&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()() &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; T; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *s) &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; T(s); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; std::string &amp;amp;s) &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; T(s); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  } local;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &amp;amp;local;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It'd be nice to return a reference instead of a pointer, but dealing with references in std::map is kind of icky. We can use macros to cleanup any annoying pointer dereferencing issues that could arise.&lt;br /&gt;&lt;br /&gt;Now our construct function returns a pointer to an interface which can construct a derived type using any of its constructors. We'll use it with an std::map like so:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;std::map&amp;lt;std::string, &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; construct_interface *&amp;gt; factory;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;factory[&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"base"&lt;/span&gt;&lt;span style="color: #000000;"&gt;] = construct&amp;lt;base&amp;gt;();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;factory[&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"derived"&lt;/span&gt;&lt;span style="color: #000000;"&gt;] = construct&amp;lt;derived&amp;gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Notice the map no longer tracks function pointers, but pointers to the interface. Also, when assigning to the map, we're calling the construct function to obtain the pointer. We could modify the above example to track function pointers and leave out the (), and even make the construct function return a reference to an interface instead, but then we'd need to add an extra () when creating objects. While that too can be hidden by a macro, or just ignored, as an extra () still looks rather clean, it does add extra overhead, as it is likely you'll initialize your map just once, and use it to create many objects during the lifetime of the program.&lt;br /&gt;&lt;br /&gt;Now to use the map to create an object, the following has to be done:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Use first constructor, the default constructor&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;base *obj1 = (*(factory).at(id))();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Use second constructor, the one taking a C string&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;base *obj2 = (*(factory).at(id))(s);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It works nicely, but as I explained above that's rather ugly.&lt;br /&gt;&lt;br /&gt;This macro can help simplify things:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;#define VIRTUAL_NEW(factory, id) (*(factory).at((id)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And unlike the interface class and template construction function which needs to be created for each set of classes making use of virtual constructors, the above macro can be reused for every virtual constructor collection that makes use of the above idiom.&lt;br /&gt;&lt;br /&gt;Using the macro, the code now looks as follows:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Use first constructor, the default constructor&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;base *obj1 = VIRTUAL_NEW(factory, id)();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Use second constructor, the one taking a C string&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;base *obj2 = VIRTUAL_NEW(factory, id)(s);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's it, problem solved!&lt;br /&gt;&lt;br /&gt;Putting it all together, here's a working example:&lt;br /&gt;&lt;pre style="background-color:#F5F2D5"&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;#include &amp;lt;map&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;#include &amp;lt;cstdlib&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; base&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; x, y;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  base() : x(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;), y(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  base(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *s) : x(std::atoi(s)), y(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  base(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; std::string &amp;amp;s) : x(std::atoi(s.c_str())), y(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;4&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;virtual&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()() { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; x+y; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; derived : &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; base&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  derived() {}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  derived(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *s) : base(s) {}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  derived(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; std::string &amp;amp;s) : base(s) {}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;virtual&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()() { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; x*y; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;struct&lt;/span&gt;&lt;span style="color: #000000;"&gt; construct_interface&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;virtual&lt;/span&gt;&lt;span style="color: #000000;"&gt; base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()() &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; = &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;virtual&lt;/span&gt;&lt;span style="color: #000000;"&gt; base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *) &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; = &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;virtual&lt;/span&gt;&lt;span style="color: #000000;"&gt; base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; std::string &amp;amp;) &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; = &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;template&lt;/span&gt;&lt;span style="color: #000000;"&gt; &amp;lt;&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;typename&lt;/span&gt;&lt;span style="color: #000000;"&gt; T&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; construct_interface *construct()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="color: #800000;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;struct&lt;/span&gt;&lt;span style="color: #000000;"&gt; : &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; construct_interface&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()() &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; T; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *s) &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; T(s); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    base *&lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;operator&lt;/span&gt;&lt;span style="color: #000000;"&gt;()(&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; std::string &amp;amp;s) &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; { &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; T(s); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  } local;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &amp;amp;local;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;#define VIRTUAL_NEW(factory, id) (*(factory).at((id)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; main(&lt;/span&gt;&lt;span style="color: #800000;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; argc, &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; *&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; *&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; argv)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  std::map&amp;lt;std::string, &lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; construct_interface *&amp;gt; factory;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  factory[&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"b"&lt;/span&gt;&lt;span style="color: #000000;"&gt;] = construct&amp;lt;base&amp;gt;();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  factory[&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"d"&lt;/span&gt;&lt;span style="color: #000000;"&gt;] = construct&amp;lt;derived&amp;gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (argc == &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;try&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Instantiate based on run-time variables&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      base *obj1 = VIRTUAL_NEW(factory, argv[&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;])();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      base *obj2 = VIRTUAL_NEW(factory, argv[&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;])(argv[&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;]);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      base *obj3 = VIRTUAL_NEW(factory, argv[&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;])(std::string(argv[&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;]));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Output&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      std::cout &amp;lt;&amp;lt; (*obj1)() &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;'\n'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;                &amp;lt;&amp;lt; (*obj2)() &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;'\n'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;                &amp;lt;&amp;lt; (*obj3)() &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;'\n'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;                &amp;lt;&amp;lt; std::flush;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="font-style: italic;color: #808080;"&gt;//Cleanup&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;delete&lt;/span&gt;&lt;span style="color: #000000;"&gt; obj1;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;delete&lt;/span&gt;&lt;span style="color: #000000;"&gt; obj2;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;      &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;delete&lt;/span&gt;&lt;span style="color: #000000;"&gt; obj3;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;catch&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #800000;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; std::exception &amp;amp;e) { std::cout &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Error occured: "&lt;/span&gt;&lt;span style="color: #000000;"&gt; &amp;lt;&amp;lt; e.what() &amp;lt;&amp;lt; std::endl; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="font-weight: bold;color: #000000;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/tmp&amp;gt; g++-4.4 -Wall -o abstract_factory_test abstract_factory_test.cpp&lt;br /&gt;/tmp&amp;gt; ./abstract_factory_test b 2&lt;br /&gt;3&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;/tmp&amp;gt; ./abstract_factory_test b 3&lt;br /&gt;3&lt;br /&gt;6&lt;br /&gt;7&lt;br /&gt;/tmp&amp;gt; ./abstract_factory_test d 2&lt;br /&gt;2&lt;br /&gt;6&lt;br /&gt;8&lt;br /&gt;/tmp&amp;gt; ./abstract_factory_test d 3&lt;br /&gt;2&lt;br /&gt;9&lt;br /&gt;12&lt;br /&gt;/tmp&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Hopefully you should now be able to take this example and plug it in just about anywhere. Easy to add new types. No need to modify existing classes. Fully dynamic. Easy to use!&lt;br /&gt;&lt;br /&gt;This method really shines if you dynamically load derived classes while your program is running. Just make sure your DLL uses the the template function internally, so an instance of the function for the new type is created, and dynamically add an id to the map, and presto you're done.&lt;br /&gt;&lt;br /&gt;Now go out there and leverage the power of C++!</description><link>http://insanecoding.blogspot.com/2010/07/simplifying-bootstrapping-for-virtual.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-2502595210222735372</guid><pubDate>Tue, 20 Jul 2010 13:55:00 +0000</pubDate><atom:updated>2013-04-02T19:38:24.273-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>good code</category><category domain='http://www.blogger.com/atom/ns#'>types</category><category domain='http://www.blogger.com/atom/ns#'>pure failure</category><category domain='http://www.blogger.com/atom/ns#'>Function Pointers</category><category domain='http://www.blogger.com/atom/ns#'>binary</category><category domain='http://www.blogger.com/atom/ns#'>bad code</category><category domain='http://www.blogger.com/atom/ns#'>insane ideas</category><category domain='http://www.blogger.com/atom/ns#'>factory</category><category domain='http://www.blogger.com/atom/ns#'>Optimization</category><title>Time to shutdown the factory for code violations</title><description>There's a common problem in software development regarding how to create an object's type dynamically in C++ and similar languages. If I have a collection of classes (they all inherit from the same base), I can use a base pointer to any instance, and perform operations as needed. The issue is generating that pointer in the first place.&lt;br /&gt;&lt;br /&gt;Say I have an image class, with subclasses of image_png, image_jpeg, image_gif, and so on. I can use an image pointer along with its virtual functions to do an operation like image_pointer-&amp;gt;resize(new_dimensions), and have it do whatever needs to be done for the image type in question to resize it and write the data properly.&lt;br /&gt;&lt;br /&gt;This idea applies to all kinds of projects over and over again. Another example could be a compression class. Where I have the class compress, along with subclasses compress_zip, compress_gzip, compress_7zip, and so on. I can do compress_pointer-&amp;gt;uncompress(in_file, out_file), and have that work appropriately with virtual functions.&lt;br /&gt;&lt;br /&gt;However my image pointer and my compress pointer need to be pointing at the right kind of object for this to work in the first place. My image is sent over the network, I have information at runtime of image/jpeg and the binary data, and I need to load that into the correct subclass image_jpeg. My compressed file is on the hard drive, I read its type via its extension or its header, again I need my pointer to point at the appropriate subtype. I don't have this information at compile time, so how do I initialize my pointer?&lt;br /&gt;&lt;br /&gt;In this case, the idea of virtual constructors, or &lt;a href="http://en.wikipedia.org/wiki/Factory_%28software_concept%29"&gt;factories&lt;/a&gt; come into play. The simplest factory would be in the form of an if/else if structure, or a switch.&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: black;"&gt;image *image_factory(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *mime_type, &lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;uint8_t&lt;/span&gt;&lt;span style="color: black;"&gt; *binary_data, size_t size)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  image *image_pointer;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (!strcmp(mime_type, &lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"image/jpeg"&lt;/span&gt;&lt;span style="color: black;"&gt;)) { image_pointer = &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; image_jpeg(binary_data, size); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;else&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (!strcmp(mime_type, &lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"image/png"&lt;/span&gt;&lt;span style="color: black;"&gt;)) { image_pointer = &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; image_png(binary_data, size); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;else&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (!strcmp(mime_type, &lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"image/gif"&lt;/span&gt;&lt;span style="color: black;"&gt;)) { image_pointer = &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; image_gif(binary_data, size); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;else&lt;/span&gt;&lt;span style="color: black;"&gt; { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;throw&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;amp;nbsp&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Unsupported image type"&lt;/span&gt;&lt;span style="color: black;"&gt;; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; image_pointer;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: black;"&gt;compress *compress_factory(COMPRESS_TYPES requested_save_format)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  compress *compress_pointer;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;switch&lt;/span&gt;&lt;span style="color: black;"&gt; (requested_save_format)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;case&lt;/span&gt;&lt;span style="color: black;"&gt; COMPRESS_ZIP: compress_pointer = &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; compress_zip; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;break&lt;/span&gt;&lt;span style="color: black;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;case&lt;/span&gt;&lt;span style="color: black;"&gt; COMPRESS_GZIP: compress_pointer = &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; compress_gzip; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;break&lt;/span&gt;&lt;span style="color: black;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;case&lt;/span&gt;&lt;span style="color: black;"&gt; COMPRESS_7ZIP: compress_pointer = &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; compress_7zip; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;break&lt;/span&gt;&lt;span style="color: black;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;default&lt;/span&gt;&lt;span style="color: black;"&gt;: &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;throw&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;nbsp;std::runtime_error(&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Unknown enum value"&lt;/span&gt;&lt;span style="color: black;"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; compress_pointer;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now the above functions allow us to get the base pointer initialized appropriately, but they have some drawbacks.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;A single function needs to know about every type.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If which types are supported changes during runtime, perhaps based on which DLLs are found, the factory function becomes more complex, and has to be specifically tailored for each application.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If there are multiple constructors, and in some cases one is needed, and in some cases another, suddenly we need to recreate the same logic in multiple factory functions, one factory function per constructor.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;This style of factory function has to be recreated for every single collection of classes present, the logic behind a factory function is not abstracted away.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Based on these drawbacks, obviously such a method is the incorrect solution, even though it is the most &lt;a href="http://en.wikipedia.org/wiki/Factory_method_pattern"&gt;popular method used&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;In the case where we have variables mapping to other variables, such as 1 = "Apple", 2 = "Orange", 3 = "Tomato", the obvious solution would be to setup an array or use a &lt;a href="http://en.wikipedia.org/wiki/Map_%28C%2B%2B%29"&gt;map&lt;/a&gt;. If the mapping needed is between an integer and a variable, going from integer -&amp;gt; variable is simply a matter of indexing into an array. When dealing with non integer types, the standard &lt;a href="http://www.cplusplus.com/reference/stl/map/"&gt;std::map&lt;/a&gt; fits the bill rather nicely, as it can allow any type to become an index.&lt;br /&gt;&lt;br /&gt;So the question becomes, can we map a variable to a type itself? With a bit of bootstrapping, the answer is actually yes! What we need are &lt;a href="http://insanecoding.blogspot.com/2007/05/secrets-to-optimization-function.html"&gt;function pointers to replace code logic&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We can't create a function pointer directly to a constructor, so we'll need a bit of bootstrapping. We can create function pointers to global functions, or &lt;a href="http://www.learncpp.com/cpp-tutorial/812-static-member-functions/"&gt;static member functions&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;In our compression case we can do the following:&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: maroon;"&gt;static&lt;/span&gt;&lt;span style="color: black;"&gt; compress *compress_zip::construct() { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; compress_zip; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: maroon;"&gt;static&lt;/span&gt;&lt;span style="color: black;"&gt; compress *compress_gzip::construct() { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; compress_gzip; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: maroon;"&gt;static&lt;/span&gt;&lt;span style="color: black;"&gt; compress *compress_7zip::construct() { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; compress_7zip; }&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We'll place a static construct() within each of our classes we'd like to be able to instantiate dynamically, and then we can use them in a map like so:&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: black;"&gt;std::map&amp;lt;COMPRESS_TYPES, compress *(*)()&amp;gt; compress_factory;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;compress_factory[COMPRESS_ZIP] = compress_zip::construct;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;compress_factory[COMPRESS_GZIP] = compress_gzip::construct;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;compress_factory[COMPRESS_7ZIP] = compress_7zip::construct;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Once we have a map in place that can be constructed at runtime, we no longer have most of our above issues. No canned function needs to be created which knows about all the supported types in advance, which needs modification for each new type. Values are only added to the map that the required DLLs were found for it, or other runtime constraints. The entire idea is also abstracted away, and we don't need to constantly recreate new factory functions for each family of objects. We simply just initialize a factory object and make use of it.&lt;br /&gt;&lt;br /&gt;Now how exactly do we use our map? The idea which is rather popular and expounded in book after book, is to create a factory template class something similar to the following:&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: black; font-weight: bold;"&gt;template&lt;/span&gt;&lt;span style="color: black;"&gt; &amp;lt;&lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;typename&lt;/span&gt;&lt;span style="color: black;"&gt; identifier, &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;typename&lt;/span&gt;&lt;span style="color: black;"&gt; product, &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;typename&lt;/span&gt;&lt;span style="color: black;"&gt; function&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;struct&lt;/span&gt;&lt;span style="color: black;"&gt; factory&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: maroon;"&gt;void&lt;/span&gt;&lt;span style="color: black;"&gt; set_mapping(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; identifier &amp;amp;id, function f) { mapping[id] = f; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  product *construct(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; identifier &amp;amp;id)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    function f = mapping.at(id);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; f();&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;private&lt;/span&gt;&lt;span style="color: black;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  std::map&amp;lt;identifier, function&amp;gt; mapping;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now that we have all that encapsulated, we can do the following:&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: black;"&gt;factory&amp;lt;COMPRESS_TYPES, compress, compress *(*)()&amp;gt; myfactory;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;myfactory.set_mapping(COMPRESS_ZIP, compress_zip::construct);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;compress *compress_pointer = myfactory.construct(requested_save_format);&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;However, such a method has a serious drawback. What if my constructor needs parameters? As it does in the image example above? Do I end up creating a new factory encapsulation class each time? &lt;a href="http://loki-lib.cvs.sourceforge.net/viewvc/loki-lib/loki/include/loki/Factory.h?revision=1.17&amp;amp;view=markup"&gt;One library out there solves this problem with ~800 lines of code&lt;/a&gt; (read &lt;a href="http://www.amazon.com/gp/product/0201704315/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0201704315&amp;amp;linkCode=as2&amp;amp;tag=insacodi-20"&gt;Modern C++ Design&lt;/a&gt;&lt;img alt="" border="0" class="hioyqmdriwomkxxppfkw" height="1" src="http://www.assoc-amazon.com/e/ir?t=insacodi-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0201704315" style="border: none !important; margin: 0px !important;" width="1" /&gt; for more info). Basically the construct function in the factory class is overloaded a bunch of times with template parameters over and over again, for some conceivable amount of parameters a function might take.&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: black;"&gt;AbstractProduct *CreateObject(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; IdentifierType &amp;amp;id,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;                              Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, Parm6 p6, Parm7 p7, Parm8 p8)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;typename&lt;/span&gt;&lt;span style="color: black;"&gt; IdToProductMap::iterator i = associations_.find(id);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (i != associations_.end()) { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; (i-&amp;gt;second)(p1, p2, p3, p4, p5, p6, p7, p8); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;this&lt;/span&gt;&lt;span style="color: black;"&gt;-&amp;gt;OnUnknownType(id);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The above snippet is repeated 16 times in that library with 0-15 parameters. First of all, such code commits the unforgivable sin of code repetition, and is limited to 15 parameters. What if I need more? Sin more?&lt;br /&gt;&lt;br /&gt;The entire idea of a factory which produces an object within itself needs to be shutdown. By trying to be overly clever and encapsulate more than needed, object factories turn into nothing but bloat and horrible code.&lt;br /&gt;&lt;br /&gt;Simplicity is king. Therefore, the map should NOT be encapsulated, nor should an object be directly produced. Our so called factory should only produce the appropriate mold needed to form our object.&lt;br /&gt;&lt;br /&gt;In the case of images:&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: maroon;"&gt;static&lt;/span&gt;&lt;span style="color: black;"&gt; image *image_jpeg::construct(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;uint8_t&lt;/span&gt;&lt;span style="color: black;"&gt; *binary_data, size_t size)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; image_jpeg(binary_data, size);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: maroon;"&gt;static&lt;/span&gt;&lt;span style="color: black;"&gt; image *image_png::construct(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;uint8_t&lt;/span&gt;&lt;span style="color: black;"&gt; *binary_data, size_t size)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; image_png(binary_data, size);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: maroon;"&gt;static&lt;/span&gt;&lt;span style="color: black;"&gt; image *image_gif::construct(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;uint8_t&lt;/span&gt;&lt;span style="color: black;"&gt; *binary_data, size_t size)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; image_gif(binary_data, size);&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;std::map&amp;lt;std::string, image *(*)(&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;uint8_t&lt;/span&gt;&lt;span style="color: black;"&gt; *, size_t)&amp;gt; image_factory;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;image_factory[&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"image/jpeg"&lt;/span&gt;&lt;span style="color: black;"&gt;] = image_jpeg::construct;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;image_factory[&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"image/png"&lt;/span&gt;&lt;span style="color: black;"&gt;] = image_png::construct;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;image_factory[&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"image/gif"&lt;/span&gt;&lt;span style="color: black;"&gt;] = image_gif::construct;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now to create an image, simply do the following when you want to create an image based on run time variables:&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: black;"&gt;image *image_pointer = image_factory.at(mime_type)(binary_data, size);&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Notice that code would take the place of:&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: black;"&gt;image *image_pointer = &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; image_png(binary_data, size);&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now the creation of a particular object at runtime looks pretty much like creating a specific object, and can feel natural. Just like new which throws an error when it fails (which can happen here too), std::map::at() throws an error when the requested index is not found, so you can reuse the same type of exception handling you're already using when creating objects in general.&lt;br /&gt;&lt;br /&gt;If you'd like a complete example which you can play with yourself, try this:&lt;br /&gt;&lt;pre style="background-color: #f5f2d5;"&gt;&lt;span style="color: green;"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;map&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;stdexcept&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;#include &amp;lt;cstdlib&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;class&lt;/span&gt;&lt;span style="color: black;"&gt; Base&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; x, y;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;public&lt;/span&gt;&lt;span style="color: black;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  Base(&lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; x, &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; y) : x(x), y(y) {}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;virtual&lt;/span&gt;&lt;span style="color: black;"&gt; ~Base() {};&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;virtual&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; mult() { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; x*y; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;virtual&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; add() { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; x+y; }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: maroon;"&gt;static&lt;/span&gt;&lt;span style="color: black;"&gt; Base *create(&lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; x, &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; y) { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; Base(x, y); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black; font-weight: bold;"&gt;class&lt;/span&gt;&lt;span style="color: black;"&gt; Derived : &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;public&lt;/span&gt;&lt;span style="color: black;"&gt; Base&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; z;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;public&lt;/span&gt;&lt;span style="color: black;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  Derived(&lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; x, &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; y) : Base(x, y), z(&lt;/span&gt;&lt;span style="color: blue;"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;) {}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: maroon;"&gt;void&lt;/span&gt;&lt;span style="color: black;"&gt; setZ(&lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; z) { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;this&lt;/span&gt;&lt;span style="color: black;"&gt;-&amp;gt;z = z; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;virtual&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; mult() { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; Base::mult()*z; }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;virtual&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; add() { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; Base::add()+z; }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: maroon;"&gt;static&lt;/span&gt;&lt;span style="color: black;"&gt; Base *create(&lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; x, &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; y) { &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;new&lt;/span&gt;&lt;span style="color: black;"&gt; Derived(x, y); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; main(&lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt; argc, &lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: maroon;"&gt;char&lt;/span&gt;&lt;span style="color: black;"&gt; *&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; *&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; argv)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Get factory ready&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  std::map&amp;lt;std::string, Base *(*)(&lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: maroon;"&gt;int&lt;/span&gt;&lt;span style="color: black;"&gt;)&amp;gt; factory;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Add some rules&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  factory[&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"base"&lt;/span&gt;&lt;span style="color: black;"&gt;] = Base::create;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  factory[&lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"derived"&lt;/span&gt;&lt;span style="color: black;"&gt;] = Derived::create;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;try&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Instantiate based on run-time variables&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    Base *obj = factory.at(argv[&lt;/span&gt;&lt;span style="color: blue;"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;])(&lt;/span&gt;&lt;span style="color: blue;"&gt;4&lt;/span&gt;&lt;span style="color: black;"&gt;, &lt;/span&gt;&lt;span style="color: blue;"&gt;5&lt;/span&gt;&lt;span style="color: black;"&gt;); &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Note: instead of new Base(4, 5) or new Derived(4, 5)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Set Z if derived and requested&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (argc &amp;gt; &lt;/span&gt;&lt;span style="color: blue;"&gt;2&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;      &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt; (Derived *d = &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;dynamic_cast&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;lt;Derived *&amp;gt;(obj)) { d-&amp;gt;setZ(std::atoi(argv[&lt;/span&gt;&lt;span style="color: blue;"&gt;2&lt;/span&gt;&lt;span style="color: black;"&gt;])); }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Output&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    std::cout &amp;lt;&amp;lt; obj-&amp;gt;mult() &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: magenta;"&gt;' '&lt;/span&gt;&lt;span style="color: black;"&gt; &amp;lt;&amp;lt; obj-&amp;gt;add() &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: grey; font-style: italic;"&gt;//Cleanup&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;delete&lt;/span&gt;&lt;span style="color: black;"&gt; obj;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;catch&lt;/span&gt;&lt;span style="color: black;"&gt; (&lt;/span&gt;&lt;span style="color: maroon;"&gt;const&lt;/span&gt;&lt;span style="color: black;"&gt; std::exception &amp;amp;e) { std::cout &amp;lt;&amp;lt; &lt;/span&gt;&lt;span style="color: #dd0000;"&gt;"Error occured: "&lt;/span&gt;&lt;span style="color: black;"&gt; &amp;lt;&amp;lt; e.what() &amp;lt;&amp;lt; std::endl; }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;  &lt;/span&gt;&lt;span style="color: black; font-weight: bold;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; &lt;/span&gt;&lt;span style="color: blue;"&gt;0&lt;/span&gt;&lt;span style="color: black;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: black;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here's what the output looks like:&lt;br /&gt;&lt;pre&gt;/tmp&amp;gt; g++-4.4 -Wall -o factory_test factory_test.cpp&lt;br /&gt;/tmp&amp;gt; ./factory_test&lt;br /&gt;Error occured: basic_string::_S_construct NULL not valid&lt;br /&gt;/tmp&amp;gt; ./factory_test base&lt;br /&gt;20 9&lt;br /&gt;/tmp&amp;gt; ./factory_test derived&lt;br /&gt;20 10&lt;br /&gt;/tmp&amp;gt; ./factory_test derived 6&lt;br /&gt;120 15&lt;br /&gt;/tmp&amp;gt; ./factory_test cows&lt;br /&gt;Error occured: map::at&lt;br /&gt;/tmp&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Basically the only issue we're left with is that for each class you want to be able to use a factory for, you have to create a static member function for each constructor you want to use with a particular factory. I don't think there is away around that. It's a minor inconvenience, but in the end offers a lot of power in a clean fashion.&lt;br /&gt;&lt;br /&gt;This idea of combining a map with a function pointer can be expanded to other areas as well. You can use this method for calling functions in general based on any runtime input. If your class has many different member functions, each with the same parameters, but for different operations, consider creating a map to &lt;a href="http://www.parashift.com/c%2B%2B-faq-lite/pointers-to-members.html"&gt;member function pointers&lt;/a&gt;, and use the input as an index into a map to call the appropriate member function.&lt;br /&gt;&lt;br /&gt;Suggestions, improvements, and comments welcome.</description><link>http://insanecoding.blogspot.com/2010/07/time-to-shutdown-factory-for-code.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>12</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-1742684663998488556</guid><pubDate>Thu, 03 Jun 2010 21:19:00 +0000</pubDate><atom:updated>2010-06-03T14:56:15.083-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Mozilla</category><category domain='http://www.blogger.com/atom/ns#'>Library</category><category domain='http://www.blogger.com/atom/ns#'>Windows</category><category domain='http://www.blogger.com/atom/ns#'>iphone</category><category domain='http://www.blogger.com/atom/ns#'>closed source</category><category domain='http://www.blogger.com/atom/ns#'>Firefox</category><category domain='http://www.blogger.com/atom/ns#'>competition</category><category domain='http://www.blogger.com/atom/ns#'>open source</category><category domain='http://www.blogger.com/atom/ns#'>bugs</category><category domain='http://www.blogger.com/atom/ns#'>parameters</category><category domain='http://www.blogger.com/atom/ns#'>pure failure</category><category domain='http://www.blogger.com/atom/ns#'>compatibility</category><category domain='http://www.blogger.com/atom/ns#'>API</category><category domain='http://www.blogger.com/atom/ns#'>binary</category><category domain='http://www.blogger.com/atom/ns#'>Mac OS X</category><category domain='http://www.blogger.com/atom/ns#'>Portability</category><category domain='http://www.blogger.com/atom/ns#'>Optimization</category><title>Undocumented APIs</title><description>This topic has been kicked around all over for at least a decade. It's kind of hard to read a computer programming magazine, third party documentation, technology article site, third party developer mailing list or the like without running into it.&lt;br /&gt;&lt;br /&gt;Inevitably someone always mentions how some Operating System has undocumented APIs, and the creators of the OS are using those undocumented APIs, but telling third party developers not to use them. There will always be the rant about unfair competition, hypocrisy, and other evils.&lt;br /&gt;&lt;br /&gt;Large targets are Microsoft and Apple, for creating undocumented APIs that are used by Internet Explorer, Microsoft Office, Safari, iPhone development, and other in-house applications. To the detriment of Mozilla, OpenOffice.org, third parties, and hobbyist developer teams.&lt;br /&gt;&lt;br /&gt;If you wrote one of those articles/rants/complaints, or agreed with them, I'm asking you to turn in your Geek Membership card now. You're too stupid, too idiotic, too dumb, too nearsighted, and too vilifying (add other derogatory adjectives you can think of) to be part of our club. You have no business writing code or even discussing programming.&lt;br /&gt;&lt;br /&gt;Operating Systems and other applications that communicate via APIs provide public interfaces that are supposed to be stable. If you find a function in official public documentation, that generally signifies it is safe to use the function in question, and the company will support it for the foreseeable future versions. If a function is undocumented, it's because the company doesn't think they will be supporting the function long term.&lt;br /&gt;&lt;br /&gt;Now new versions which provide even the exact same API inevitably break things. It is so much worse for APIs which you're not supposed to be using in the first place. Yet people who complain about undocumented APIs, also complain when the new version removes a function they were using. They blame the company for purposely removing features they knew competition or hobbyists were using. That's where the real hypocrisy is.&lt;br /&gt;&lt;br /&gt;As much as you hate a new version breaking your existing software, so does Microsoft, Apple, and others. The popularity of their products is tied to what third party applications exist. Having popular third party applications break on new versions is a bad thing. That's why they don't document APIs they plan on changing.&lt;br /&gt;&lt;br /&gt;Now why do they use them then? Simple, you can write better software when you intimately understand the platform you're developing for, and write the most direct code possible. When issues occur because of their use, it's easy for the in-house teams to test their own software for compatibility with upcoming versions and fix them. If Microsoft sees a new version of Windows break Internet Explorer, they can easily patch the Internet Explorer provided with the upcoming version, or provide a new version altogether. But don't expect them to go patching third party applications, especially ones which they don't have the source to. They may have done so in the past, and introduced compatibility hacks, but this really isn't their problem, and you should be grateful when they go out of their way to do so.&lt;br /&gt;&lt;br /&gt;So quit your complaining about undocumented APIs, or please go around introducing yourself as "&lt;a href="http://www.dilbert.com/dyn/str_strip/000000000/00000000/0000000/000000/00000/1000/200/1233/1233.strip.print.gif"&gt;The Dumb One&lt;/a&gt;".</description><link>http://insanecoding.blogspot.com/2010/06/undocumented-apis.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-4615312562166259836</guid><pubDate>Sat, 27 Mar 2010 22:21:00 +0000</pubDate><atom:updated>2010-03-28T01:14:30.924-07:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>x86-64</category><category domain='http://www.blogger.com/atom/ns#'>Library</category><category domain='http://www.blogger.com/atom/ns#'>bad code</category><category domain='http://www.blogger.com/atom/ns#'>C++-0x</category><category domain='http://www.blogger.com/atom/ns#'>unsigned</category><category domain='http://www.blogger.com/atom/ns#'>bugs</category><category domain='http://www.blogger.com/atom/ns#'>good code</category><category domain='http://www.blogger.com/atom/ns#'>parameters</category><category domain='http://www.blogger.com/atom/ns#'>types</category><category domain='http://www.blogger.com/atom/ns#'>signed</category><category domain='http://www.blogger.com/atom/ns#'>pure failure</category><category domain='http://www.blogger.com/atom/ns#'>x86</category><category domain='http://www.blogger.com/atom/ns#'>API</category><category domain='http://www.blogger.com/atom/ns#'>binary</category><category domain='http://www.blogger.com/atom/ns#'>secure</category><category domain='http://www.blogger.com/atom/ns#'>C++-201x</category><category domain='http://www.blogger.com/atom/ns#'>c99</category><category domain='http://www.blogger.com/atom/ns#'>standards compliance</category><category domain='http://www.blogger.com/atom/ns#'>language</category><category domain='http://www.blogger.com/atom/ns#'>Portability</category><title>Does anyone understand types and magnitudes?</title><description>Regularly I have to work with many popular libraries out there, as well as many libraries written by coworkers and similar.&lt;br /&gt;&lt;br /&gt;One thing which I see constantly misused over and over again is the type system used in C and C++.&lt;br /&gt;&lt;br /&gt;I wonder if most people understand it, have bothered to contemplate it, or simply don't care if their library is misprogrammed trash.&lt;br /&gt;&lt;br /&gt;First of all, C/C++ for integers supports both &lt;span style="font-style:italic;"&gt;signed&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;unsigned&lt;/span&gt; types. Many programmers seem to ignore the unsigned types altogether. Maybe some education is in order.&lt;br /&gt;&lt;br /&gt;Each base type in C consists of one or more bytes. Each byte on modern main stream systems are 8 bits to a byte. Meaning a single byte can store &lt;span style="font-family: arial;"&gt;&lt;span style="font-weight:bold;font-size:large;"&gt;2&lt;/span&gt;&lt;sup style="font-size:x-small;"&gt;8&lt;/sup&gt;&lt;/span&gt; values, or in other words &lt;span style="font-family: arial;"&gt;256&lt;/span&gt; possibilities. Two bytes can store &lt;span style="font-family: arial;"&gt;&lt;span style="font-weight:bold;font-size:large;"&gt;2&lt;/span&gt;&lt;sup style="font-size:x-small;"&gt;16&lt;/sup&gt;&lt;/span&gt; values, or in other words &lt;span style="font-family: arial;"&gt;65,536&lt;/span&gt; possibilities.&lt;br /&gt;&lt;br /&gt;A type designed for integers (whole numbers) which is unsigned will operate with the meaning of its values as ranging from 0 till amount of possibilities - 1. In the case of a one byte type: 0 to &lt;span style="font-family: arial;"&gt;255&lt;/span&gt;, for a 2 byte type: 0 to &lt;span style="font-family: arial;"&gt;65,535&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;When a value is signed (the usual default if no &lt;span style="font-style:italic;"&gt;signed&lt;/span&gt; or &lt;span style="font-style:italic;"&gt;unsigned&lt;/span&gt; description is applied), a single bit is used to describe whether the rest of the bits represent a positive or negative value. This effectively cuts the amount of positive values that can be represented in half. In the case of a single byte, &lt;span style="font-family: arial;"&gt;&lt;span style="font-weight:bold;font-size:large;"&gt;2&lt;/span&gt;&lt;sup style="font-size:x-small;"&gt;7&lt;/sup&gt;&lt;/span&gt; values will be negative, &lt;span style="font-family: arial;"&gt;-128&lt;/span&gt; to -1, &lt;span style="font-family: arial;"&gt;&lt;span style="font-weight:bold;font-size:large;"&gt;2&lt;/span&gt;&lt;sup style="font-size:x-small;"&gt;7&lt;/sup&gt;&lt;/span&gt;-1 values will be distinctly positive, 1 to &lt;span style="font-family: arial;"&gt;127&lt;/span&gt;, and one value will be 0 (for a total of &lt;span style="font-family: arial;"&gt;256&lt;/span&gt; possibilities). This same math extends to as many bytes being used in a given type.&lt;br /&gt;&lt;br /&gt;When dealing with something which requires working with both positive and negative values such as debt (monetary balance), direction, difference, relative position, and things of a similar nature, signed values is quite natural and should of course be used.&lt;br /&gt;&lt;br /&gt;But if you're working with something which has no meaning for negative values such as "Number of students in this class", "How old are you", "Amount of chickens in the coop", "Amount of rows in database table", or "Amount of elements in this array", or amounts of any nature really, using a signed type is one of the worst things you could possibly do. You are reserving half of your possible values for a situation which will never occur (barring mistakes in programming).&lt;br /&gt;&lt;br /&gt;Let's take a look at some real world examples. The most popular type used for at least the past decade would have to be the 32 bit integer. &lt;span style="font-family: arial;"&gt;&lt;span style="font-weight:bold;font-size:large;"&gt;2&lt;/span&gt;&lt;sup style="font-size:x-small;"&gt;32&lt;/sup&gt;&lt;/span&gt; gives us &lt;span style="font-family: arial;"&gt;4,294,967,296&lt;/span&gt; different value possibilities. If that was a storage size, it would be 4GB. Effectively a 32 bit unsigned integer can store the values 0 to &lt;span style="font-family: arial;"&gt;4,294,967,295&lt;/span&gt;, or one byte less than 4GB. If it was signed, it would be able to store the values &lt;span style="font-family: arial;"&gt;-2,147,483,648&lt;/span&gt; to &lt;span style="font-family: arial;"&gt;2,147,483,6487&lt;/span&gt;, topping out at one less than 2GB.&lt;br /&gt;&lt;br /&gt;If you have an Operating System or File System which limits you to 2GB as a max size for files, or your Digital Camera only lets you use up to 2GB flash cards, it's because the idiots that programmed it used signed values. They did this because either they were expecting files and flash cards of negative size, or because they were a bunch of idiots. Which of those two possibilities actually happened should be obvious.&lt;br /&gt;&lt;br /&gt;The same goes for any programming library you see with a limit of 2GB. As soon as you hear anyone mention a limitation of 2GB, what should immediately register in your head is that idiots worked on this application/library/standard/device.&lt;br /&gt;&lt;br /&gt;Now sometimes programmers try to justify their ignorance or their idiocy with remarks such as using negative values to indicate error conditions. Meaning, they write functions which return a positive value in case of success, and -1 in case of error. This is a very bad practice for two reasons. First of all, one shouldn't use a single variable to indicate two different things. It's okay to use a single variable where each bit (or sets of bits) indicate a flag for a set of flags. But it's very wrong to have a single value indicate success/failure and amount, or day of week and favorite color, or any two completely unrelated things like that. Doing so only leads to sloppy code, and should always be avoided. Second of all, you're cutting your amount of usable possibilities in half, and reserving a ton of values just for a single possibility. You can't be more wasteful than that.&lt;br /&gt;&lt;br /&gt;If you need a way for your function to return success/failure and amount, there are cleaner and more effective ways to do so. Many times an amount of 0 is invalid. If a function is supposed to return the amount of something, 0 isn't really an amount. If I asked how many students are in my class, and I get 0, that in itself should be indicative of an error. If I asked how many rows did my SQL statement just change, and I get 0, that should be indicative of an error, or at the very least, there were no SQL rows to change. If I really need to know if the 0 means a real error, or there was no data to work with, a separate function can tell me if the last call was a success or failure. In C and in POSIX, it is common to use the global variable &lt;span style="font-style:italic;"&gt;errno&lt;/span&gt; to indicate errors. If you're making your own library, you can make a function to tell you &lt;span style="font-style:italic;"&gt;why&lt;/span&gt; the last value was 0. There was no data, there was an error accessing the data, and so on.&lt;br /&gt;&lt;br /&gt;Another method would be to pass one parameter by pointer/reference to store the amount or success state, and have the other returned from the function. Another technique would be to return an &lt;span style="font-style:italic;"&gt;enum&lt;/span&gt; which tells you which error condition happened or everything is okay, and use a different function to retrieve the value of that operation upon success. Lastly, C++ programmers can use std::pair&lt;&gt; for all their multiple return needs, or simply return the amount normally, and throw an exception on any kind of error.&lt;br /&gt;&lt;br /&gt;Now that hopefully all my loyal readers are now more educated about the sign of their types, and various function return techniques that better libraries use, let's talk a bit about magnitude.&lt;br /&gt;&lt;br /&gt;I see again and again libraries that don't have a clue about magnitude. The various C/C++ standards state the following about the normal built in types.&lt;br /&gt;&lt;br /&gt;1) The amount of bytes used for the following types should be in this proportion: short &lt;= int &lt;= long &lt;= long long.&lt;br /&gt;2) short should be &lt;span style="font-weight:bold;"&gt;at least&lt;/span&gt; 2 bytes.&lt;br /&gt;3) long should be &lt;span style="font-weight:bold;"&gt;at least&lt;/span&gt; 4 bytes.&lt;br /&gt;4) long long should be &lt;span style="font-weight:bold;"&gt;at least&lt;/span&gt; 8 bytes;.&lt;br /&gt;&lt;br /&gt;Which means all these scenarios are perfectly legal:&lt;br /&gt;sizeof(short) == 2&lt;br /&gt;sizeof(int) == 2&lt;br /&gt;sizeof(long) == 4&lt;br /&gt;sizeof(long long) == 8&lt;br /&gt;&lt;br /&gt;sizeof(short) == 2&lt;br /&gt;sizeof(int) == 4&lt;br /&gt;sizeof(long) == 4&lt;br /&gt;sizeof(long long) == 8&lt;br /&gt;&lt;br /&gt;sizeof(short) == 2&lt;br /&gt;sizeof(int) == 4&lt;br /&gt;sizeof(long) == 8&lt;br /&gt;sizeof(long long) == 8&lt;br /&gt;&lt;br /&gt;sizeof(short) == 2&lt;br /&gt;sizeof(int) == 4&lt;br /&gt;sizeof(long) == 8&lt;br /&gt;sizeof(long long) == 16&lt;br /&gt;&lt;br /&gt;sizeof(short) == 4&lt;br /&gt;sizeof(int) == 4&lt;br /&gt;sizeof(long) == 8&lt;br /&gt;sizeof(long long) == 16&lt;br /&gt;&lt;br /&gt;sizeof(short) == 4&lt;br /&gt;sizeof(int) == 8&lt;br /&gt;sizeof(long) == 16&lt;br /&gt;sizeof(long long) == 32&lt;br /&gt;&lt;br /&gt;And so on.&lt;br /&gt;&lt;br /&gt;In order to get types of a particular size, C99 added the header &amp;lt;stdint.h&amp;gt; and C++-201x added &amp;lt;cstdint&amp;gt;, with types such as int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, and several others. Each of these types are the size in bits that their name indicates, with those without a &lt;span style="font-style:italic;"&gt;u&lt;/span&gt; at the beginning being signed, and those with being unsigned. Using these types you can get the exact size you need.&lt;br /&gt;&lt;br /&gt;But remember to use things appropriately. I see several popular SQL engines for example that support as many rows in a table as a uint64_t is able to contain, but if you ask them how many rows were altered by the last query, they'll report that information in a plain and simple &lt;span style="font-style:italic;"&gt;int&lt;/span&gt;! You by now should realize there are two problems with such a course of action.&lt;br /&gt;&lt;br /&gt;Now lastly, if you're writing some kind of function which takes an array, it is normal convention to pass a pointer to the array, as well as a size variable to specify how many elements or bytes are within the array.&lt;br /&gt;&lt;br /&gt;The standard C library uses a type called &lt;span style="font-style:italic;"&gt;size_t&lt;/span&gt; to deal with such values. A &lt;span style="font-style:italic;"&gt;size_t&lt;/span&gt; can contain the highest amount of bytes the program is able to address, and is of course unsigned.&lt;br /&gt;&lt;br /&gt;If you need to pass an array, your prototype should always be along the lines of:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;void func(void *p, size_t size);&lt;br /&gt;void func(uint8_t *p, size_t size);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you need to return a size, for something which is addressable memory, again always use a &lt;span style="font-style:italic;"&gt;size_t&lt;/span&gt;. Functions like strlen() and sizeof() return a &lt;span style="font-style:italic;"&gt;size_t&lt;/span&gt;, and functions like memcpy(), memset(), or malloc() take a &lt;span style="font-style:italic;"&gt;size_t&lt;/span&gt; as one of their arguments.&lt;br /&gt;&lt;br /&gt;Let me show you a quick program to illustrate a point.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#include &amp;lt;cstdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#define O(x) printf(#x": %zu\n", sizeof(x))&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;  O(signed char);&lt;br /&gt;  O(signed short);&lt;br /&gt;  O(signed int);&lt;br /&gt;  O(signed long);&lt;br /&gt;  O(signed long long);&lt;br /&gt;  O(signed);&lt;br /&gt;  O(unsigned char);&lt;br /&gt;  O(unsigned short);&lt;br /&gt;  O(unsigned int);&lt;br /&gt;  O(unsigned long);&lt;br /&gt;  O(unsigned long long);&lt;br /&gt;  O(unsigned);&lt;br /&gt;  O(size_t);&lt;br /&gt;  O(void *);&lt;br /&gt;  O(float);&lt;br /&gt;  O(double);&lt;br /&gt;  O(long double);&lt;br /&gt;  return(0);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;On a 32 bit system of mine, the output is as follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;signed char: 1&lt;br /&gt;signed short: 2&lt;br /&gt;signed int: 4&lt;br /&gt;signed long: 4&lt;br /&gt;signed long long: 8&lt;br /&gt;signed: 4&lt;br /&gt;unsigned char: 1&lt;br /&gt;unsigned short: 2&lt;br /&gt;unsigned int: 4&lt;br /&gt;unsigned long: 4&lt;br /&gt;unsigned long long: 8&lt;br /&gt;unsigned: 4&lt;br /&gt;size_t: 4&lt;br /&gt;void *: 4&lt;br /&gt;float: 4&lt;br /&gt;double: 8&lt;br /&gt;long double: 12&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;On a 64 bit system of mine, the output is as follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;signed char: 1&lt;br /&gt;signed short: 2&lt;br /&gt;signed int: 4&lt;br /&gt;signed long: 8&lt;br /&gt;signed long long: 8&lt;br /&gt;signed: 4&lt;br /&gt;unsigned char: 1&lt;br /&gt;unsigned short: 2&lt;br /&gt;unsigned int: 4&lt;br /&gt;unsigned long: 8&lt;br /&gt;unsigned long long: 8&lt;br /&gt;unsigned: 4&lt;br /&gt;size_t: 8&lt;br /&gt;void *: 8&lt;br /&gt;float: 4&lt;br /&gt;double: 8&lt;br /&gt;long double: 16&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now notice for 32 bit, the &lt;span style="font-style:italic;"&gt;void *&lt;/span&gt; type is 4 bytes, and on 64 bit, it is 8 bytes. This means that a &lt;span style="font-style:italic;"&gt;void *&lt;/span&gt; can address any position in memory that the system is able to. In order to specify the amount, you'll notice in each case the &lt;span style="font-style:italic;"&gt;sizeof(size_t)&lt;/span&gt; matches the &lt;span style="font-style:italic;"&gt;sizeof(void *)&lt;/span&gt;. If I were to get a 128 bit system which had a &lt;span style="font-style:italic;"&gt;void *&lt;/span&gt; of 16 bytes, the &lt;span style="font-style:italic;"&gt;size_t&lt;/span&gt; would also be at least 16 bytes.&lt;br /&gt;&lt;br /&gt;There are other types which also matched the size of the &lt;span style="font-style:italic;"&gt;void *&lt;/span&gt; each time around, but if you look at my earlier explanation of the relationship of the various C types, you'll notice those other types are too variable to know if they'll be good for an amount of every system you try to use your application or library on, so always stick with the &lt;span style="font-style:italic;"&gt;size_t&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;All too often I see programmers use an &lt;span style="font-style:italic;"&gt;int&lt;/span&gt; for such an amount which is clearly wrong, or an &lt;span style="font-style:italic;"&gt;unsigned int&lt;/span&gt;, which is better, but also wrong, especially on my 64 bit system. Some programmers I also see use the type of just &lt;span style="font-style:italic;"&gt;unsigned&lt;/span&gt; by itself. I don't know who thought that up, but it's identical to an &lt;span style="font-style:italic;"&gt;unsigned int&lt;/span&gt;, which is also clearly wrong. I included &lt;span style="font-style:italic;"&gt;unsigned&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;signed&lt;/span&gt; specifically in my test above because some people are under the mistaken notion that those types become as large as possible. Every time I see code which contains one of them, I want to vomit.&lt;br /&gt;&lt;br /&gt;If you ever have any doubt as to what size a type may be on your system, or get into an argument with someone, test things yourself with a &lt;span style="font-style:italic;"&gt;sizeof()&lt;/span&gt; call, it's not hard to do, or point them to this article.&lt;br /&gt;&lt;br /&gt;Now go out there and write some good libraries. I have too much vomit and bile on the floor here from all the horrible code I have to work with or review.</description><link>http://insanecoding.blogspot.com/2010/03/does-anyone-understand-types-and.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>22</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-7802354735006886139</guid><pubDate>Fri, 12 Mar 2010 01:56:00 +0000</pubDate><atom:updated>2010-03-11T19:46:27.879-08:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>parameters</category><category domain='http://www.blogger.com/atom/ns#'>recursion</category><category domain='http://www.blogger.com/atom/ns#'>GCC</category><category domain='http://www.blogger.com/atom/ns#'>C++-201x</category><category domain='http://www.blogger.com/atom/ns#'>variadic templates</category><category domain='http://www.blogger.com/atom/ns#'>C++-0x</category><category domain='http://www.blogger.com/atom/ns#'>language</category><title>C++-201x Variadic Templates</title><description>C++-201x (or C++-0x as near sighted individuals like to call it) introduced a new feature called variadic templates, which allows a template class or function to recieve multiple parameters to it of various types as you would normally achieve with "...".&lt;br /&gt;&lt;br /&gt;You could continue to use stdarg if you wish, but a limitation of it is that you have no way of knowing what type each parameter is to use with va_arg(), unless you just hard code it to only work with a specific type, or pass a type list how the printf() family of functions do it, or something similar.&lt;br /&gt;&lt;br /&gt;I always wanted a way to do func(integer, string, float, whatever), and interchange that with func(float, whatever, char), and now you can.&lt;br /&gt;&lt;br /&gt;If you try to research this topic online, basically everyone is just writing and talking about how to implement a tuple class, or how to make a type safe printf. Lets try something a little more interesting and perhaps instructive, yet simple.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;//Output function to output any type without type specifiers like printf() family&lt;br /&gt;template &amp;lt;typename T, typename ...P&amp;gt;&lt;br /&gt;void output(T t, P ...p)&lt;br /&gt;{&lt;br /&gt;  cout &amp;lt;&amp;lt; t &amp;lt;&amp;lt; ' ';&lt;br /&gt;  if (sizeof...(p)) { output(p...); }&lt;br /&gt;  else { cout &amp;lt;&amp;lt; '\n'; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//Since variadic templates are recursive, must have a base case&lt;br /&gt;void output() { cout &amp;lt;&amp;lt; '\n'; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//Compute sum of all parameters&lt;br /&gt;template &amp;lt;typename T, typename ...P&amp;gt;&lt;br /&gt;T sum(T t, P ...p)&lt;br /&gt;{&lt;br /&gt;  if (sizeof...(p))&lt;br /&gt;  {&lt;br /&gt;    t += sum(p...);&lt;br /&gt;  }&lt;br /&gt;  return(t);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//Since variadic templates are recursive, must have a base case&lt;br /&gt;template &amp;lt;typename T&amp;gt;&lt;br /&gt;T sum(T t) { return(t); }&lt;br /&gt;&lt;br /&gt;//Test it&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;  output();&lt;br /&gt;  output('5');&lt;br /&gt;  output('5', 2);&lt;br /&gt;  output('5', 2, "cows");&lt;br /&gt;  output('5', 2, "cows", -1);&lt;br /&gt;  output('5', 2, "cows", -1, 0.5f);&lt;br /&gt;  output('5', 2, "cows", -1, 0.5f, 16.3);&lt;br /&gt;&lt;br /&gt;  cout &amp;lt;&amp;lt; endl;&lt;br /&gt;&lt;br /&gt;  cout &amp;lt;&amp;lt; sum(1) &amp;lt;&amp;lt; '\n'&lt;br /&gt;       &amp;lt;&amp;lt; sum(1, 2) &amp;lt;&amp;lt; '\n'&lt;br /&gt;       &amp;lt;&amp;lt; sum(1, 2, 3) &amp;lt;&amp;lt; '\n'&lt;br /&gt;       &amp;lt;&amp;lt; sum(1, 2, 3, 4) &amp;lt;&amp;lt; '\n'&lt;br /&gt;       &amp;lt;&amp;lt; sum(1, 2, 3, 4, 5) &amp;lt;&amp;lt; '\n';&lt;br /&gt;&lt;br /&gt;  cout &amp;lt;&amp;lt; endl;&lt;br /&gt;&lt;br /&gt;  cout &amp;lt;&amp;lt; sum(0.1) &amp;lt;&amp;lt; '\n'&lt;br /&gt;       &amp;lt;&amp;lt; sum(0.1, 0.2) &amp;lt;&amp;lt; '\n'&lt;br /&gt;       &amp;lt;&amp;lt; sum(0.1, 0.2, 0.3) &amp;lt;&amp;lt; '\n';&lt;br /&gt;&lt;br /&gt;  cout &amp;lt;&amp;lt; endl;&lt;br /&gt;&lt;br /&gt;  return(0);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here's how to compile and what the output looks like:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/tmp&gt; g++-4.4 -Wall -o test test.cpp -std=gnu++0x&lt;br /&gt;/tmp&gt; ./test&lt;br /&gt;&lt;br /&gt;5&lt;br /&gt;5 2&lt;br /&gt;5 2 cows&lt;br /&gt;5 2 cows -1&lt;br /&gt;5 2 cows -1 0.5&lt;br /&gt;5 2 cows -1 0.5 16.3&lt;br /&gt;&lt;br /&gt;1&lt;br /&gt;3&lt;br /&gt;6&lt;br /&gt;10&lt;br /&gt;15&lt;br /&gt;&lt;br /&gt;0.1&lt;br /&gt;0.3&lt;br /&gt;0.6&lt;br /&gt;&lt;br /&gt;/tmp&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As can be seen I achieved my desired goals of being able to pass various types, not know the types to be passed in advance, and not need a type list passed anywhere. All the other examples I've seen seem to be forgetting these important points.&lt;br /&gt;&lt;br /&gt;As for how this works "typename ...P" defines a template type of P which will be many parameters packed into a single variable. "P ...p" receives all these parameters in a variable named  "p".&lt;br /&gt;&lt;br /&gt;However the only things I can really do is see how many parameters are in "p" using "sizeof...(p)", or split "p" up into all its parameters, to then pass to a function by using "p...". It would be nice to be able to simply iterate through the values of "p", but that's not possible at the moment.&lt;br /&gt;&lt;br /&gt;Using standard recursion techniques, you can pass the split up parameters from "p" to a function which has enough templated parameters as "p" is currently holding, or a lesser amount, and the last parameter can be a variadic parameter to catch all the others which don't fit into the first few. Then using those first parameters, you can access the values you need, and so on ad infinitum.&lt;br /&gt;&lt;br /&gt;Read up on recursion if you're confused.&lt;br /&gt;&lt;br /&gt;Now if you're still wondering what this may be useful for, just consider functions which handle data serialization or something similar.&lt;br /&gt;&lt;br /&gt;One thing to note, at least with GCC at the moment, you always need to have a separate function as a base case, even if it's never used.&lt;br /&gt;&lt;br /&gt;Take "output('5', 2, "cows", -1, 0.5f, 16.3);", on the last leg of iteration, when the double is passed to the first parameter to be received by "t", and "p" is empty, "if (sizeof...(p)) { output(p...); }" which is the line responsible for the recursion seeing an empty "p" won't ask for "output()", but it seems the compiler still wants it to exist:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;test.cpp: In function ‘void output(T, P ...) [with T = double, P = ]’:&lt;br /&gt;test.cpp:8:   instantiated from ‘void output(T, P ...) [with T = float, P = double]’&lt;br /&gt;test.cpp:8:   instantiated from ‘void output(T, P ...) [with T = int, P = float, double]’&lt;br /&gt;test.cpp:8:   instantiated from ‘void output(T, P ...) [with T = const char*, P = int, float, double]’&lt;br /&gt;test.cpp:8:   instantiated from ‘void output(T, P ...) [with T = int, P = const char*, int, float, double]’&lt;br /&gt;test.cpp:8:   instantiated from ‘void output(T, P ...) [with T = char, P = int, const char*, int, float, double]’&lt;br /&gt;test.cpp:33:   instantiated from here&lt;br /&gt;test.cpp:8: error: no matching function for call to ‘output()’&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I'm not sure though if this is required by the standard, or a bug in GCC.&lt;br /&gt;&lt;br /&gt;As for C++-201x support in general, GCC seems to be the furthest ahead, even surpassing Comeau C++.&lt;br /&gt;&lt;br /&gt;See a &lt;a href="http://wiki.apache.org/stdcxx/C++0xCompilerSupport"&gt;comparison of the various compilers' support of C++-201x&lt;/a&gt;.</description><link>http://insanecoding.blogspot.com/2010/03/c-201x-variadic-templates.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>7</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-6719862338908223167</guid><pubDate>Mon, 21 Dec 2009 12:31:00 +0000</pubDate><atom:updated>2009-12-21T05:29:30.821-08:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Political Correctness</category><category domain='http://www.blogger.com/atom/ns#'>Antisemitism</category><category domain='http://www.blogger.com/atom/ns#'>Google</category><category domain='http://www.blogger.com/atom/ns#'>discrimination</category><title>Happy "Holidays" From Google</title><description>If you use GMail, you probably got this message recently:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Happy Holidays from Google    &lt;br /&gt;       &lt;br /&gt;Hello,&lt;br /&gt;&lt;br /&gt;As we near the end of the year, we wanted to take a moment to thank you for the time, energy, commitment, and trust you've shared with us in 2009.&lt;br /&gt;&lt;br /&gt;With sharing in mind, this year we've decided to do something a little different. We hope you'll find it fits the spirit of the holiday season.&lt;br /&gt;&lt;br /&gt;We're looking forward to working with you to build lasting success in 2010.&lt;br /&gt;&lt;br /&gt;Happy Holidays,&lt;br /&gt;Your Google Team&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;While on the surface it seems like a nice gesture, wouldn't it be nice if these big companies actually put some thought into what they wrote?&lt;br /&gt;&lt;br /&gt;The use of terms or "codewords" like "Happy Holidays" or "holiday season" is meant to be all inclusive of the various winter holidays celebrated by different religions or cultural groups, without singling out any one of them in particular. It's primarily meant to include minorities that celebrate &lt;a href="http://en.wikipedia.org/wiki/Kwanzaa"&gt;Kwanzaa&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Hanukkah"&gt;Hanukkah&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;But this letter was sent on December 21, after Hanukkah was already completed two days earlier. If they really wanted to be all inclusive, perhaps they should have sent it the first week in December, instead of waiting till soon after Hanukkah was over, portraying &lt;a href="http://en.wikipedia.org/wiki/Antisemitism"&gt;Antisemitism&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;All these "codewords" used are actually born out of "&lt;a href="http://en.wikipedia.org/wiki/Political_correctness"&gt;Political Correctness&lt;/a&gt;", a practice designed to discriminate against your average white male, while not actually caring about the minorities you're trying to protect. Isn't it nice to see another big company show that they aim for Political Correctness, yet show they couldn't care less about those minorities?&lt;br /&gt;&lt;br /&gt;On a similar note, a friend of mine tells me that he recently applied for a job at Google, and they sent him a form asking him to specify his &lt;a href="http://en.wikipedia.org/wiki/Race_(classification_of_human_beings)"&gt;Race&lt;/a&gt; on it. Wonder why?</description><link>http://insanecoding.blogspot.com/2009/12/happy-holidays-from-google.html</link><author>noreply@blogger.com (insane coder)</author><thr:total>5</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-3214238975534194642</guid><pubDate>Sat, 05 Dec 2009 20:17:00 +0000</pubDate><atom:updated>2009-12-05T12:35:33.617-08:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>pure failure</category><category domain='http://www.blogger.com/atom/ns#'>distribution</category><title>Cryptic Linux Distro Updates</title><description>We're almost in 2010, I thought by now to anyone who basically knows how to use a computer, general upgrade prompts in Linux Distros would make sense, and won't seem cryptic like "Abort, Retry, Ignore, Fail?".&lt;br /&gt;&lt;br /&gt;Then you get something like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vLES3KKBdaM/SxrBGC_BaFI/AAAAAAAAAHE/1EIozvZrcgQ/s1600-h/wth.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 224px;" src="http://2.bp.blogspot.com/_vLES3KKBdaM/SxrBGC_BaFI/AAAAAAAAAHE/1EIozvZrcgQ/s320/wth.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5411850211863652434" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is a new upgrade message in Debian/Ubuntu.&lt;br /&gt;Here's the full text:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Various snmp software needs extracted MIBs from RFCs and IANA - which cannot be shipped - to be working as expected. These MIBs can be automatically fetched and extracted as part of installing this package.&lt;br /&gt; &lt;br /&gt;This will take several minutes to complete, even with a fast internet connection.&lt;br /&gt;&lt;br /&gt;Download and extract MIBs from RFCs and IANA? &lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Are all these acronyms really necessary? Should a user even be given such cryptic information, and instead see a prompt along the lines of: "This package requires additional components to fully function, download them?".&lt;br /&gt;&lt;br /&gt;Even a power user who is familiar with a term like RFC, does this message even make any sense?&lt;br /&gt;&lt;br /&gt;Seems like Linux Distros still has a long way to go.</description><link>http://insanecoding.blogspot.com/2009/12/crytpic-linux-distro-updates.html</link><author>noreply@blogger.com (insane coder)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_vLES3KKBdaM/SxrBGC_BaFI/AAAAAAAAAHE/1EIozvZrcgQ/s72-c/wth.png' height='72' width='72'/><thr:total>7</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-833174317742362874.post-7208394244318228627</guid><pubDate>Tue, 24 Nov 2009 17:24:00 +0000</pubDate><atom:updated>2009-11-26T09:54:43.767-08:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>bugs</category><category domain='http://www.blogger.com/atom/ns#'>HTTP</category><category domain='http://www.blogger.com/atom/ns#'>bad code</category><category domain='http://www.blogger.com/atom/ns#'>PHB</category><category domain='http://www.blogger.com/atom/ns#'>secure</category><category domain='http://www.blogger.com/atom/ns#'>Qt</category><category domain='http://www.blogger.com/atom/ns#'>apache</category><category domain='http://www.blogger.com/atom/ns#'>protocols</category><title>Malicious hackers are not out there</title><description>Security as it is today is an illusion. What? How could I say that, I'm not serious, am I?&lt;br /&gt;&lt;br /&gt;Most people today do not understand what security is or is not about. As evidenced by so many works of modern fiction centering around a plot where the terrorists/foreign government/aliens "bug" a server, a cable, or a satellite. Today's technology is supposed to prevent attacks involving any layer in the middle being bugged. Besides not understanding what modern security is capable of, many who are working with it do not understand what it is not capable of.&lt;br /&gt;&lt;br /&gt;A quick scan of source code in many projects will turn up code which fails even text book level security principals. I even see some major projects have code commented that it needs a more secure hash or nonce generator or something similar, which again could be found in modern textbooks.&lt;br /&gt;&lt;br /&gt;It is shocking the sheer number of online services or applications one can install (forums, webmail, blog, wiki, etc...) that have insecure login. Nearly all of them take user login credentials in plain text, allowing anyone between the user's computer and the website's application to steal the passwords.&lt;br /&gt;&lt;br /&gt;It is sad that nearly all sites use a custom login scheme that can be buggy and/or receive login credentials unencrypted, considering that &lt;a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol"&gt;HTTP&lt;/a&gt; - the protocol level of communication supports secure logins. HTTP login is rarely used though because it lacks a simple way to log out (why?), and can not be made to look pretty without using &lt;a href="http://en.wikipedia.org/wiki/Ajax_(programming)"&gt;AJAX&lt;/a&gt;, which is why the vast majority of site creators avoid it.  &lt;br /&gt;&lt;br /&gt;The HTTP specifications actually describes two methods of login for "&lt;i&gt;HTTP 401&lt;/i&gt;", one called "&lt;i&gt;&lt;a href="http://en.wikipedia.org/wiki/Basic_access_authentication"&gt;Basic Authentication&lt;/a&gt;&lt;/i&gt;", and another called "&lt;i&gt;&lt;a href="http://en.wikipedia.org/wiki/Digest_access_authentication"&gt;Digest Authentication&lt;/a&gt;&lt;/i&gt;". The former transmits login credentials in plain text, and the latter using an encryption of sorts. Most sites that avoid the worry of properly creating a custom login scheme and resort to HTTP 401 generally use Basic Authentication. Historically the reason is that most developers of HTTP servers and clients have been too &lt;b&gt;stupid&lt;/b&gt; to figure out how to do it properly. Which is surprising considering it is such a simple scheme. IIS and IE didn't have it done properly till relatively recently. Apache historically has had issues with it. Qt's network classes handled it improperly until recently. I'm also told Google Chrome currently has some issues with it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;However, even if one used Digest as the login mechanism on their website, it can easily be subject to a &lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack"&gt;Man in the middle attack&lt;/a&gt;, because the HTTP spec allows for there to be the possibility of sending passwords in an unencrypted fashion.&lt;br /&gt;&lt;br /&gt;The following diagram illustrates it:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vLES3KKBdaM/SwwXvXgGGzI/AAAAAAAAAG0/ukXR9RoDnc8/s1600/backandforth1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 159px;" src="http://2.bp.blogspot.com/_vLES3KKBdaM/SwwXvXgGGzI/AAAAAAAAAG0/ukXR9RoDnc8/s320/backandforth1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5407723355095046962" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Since requests for authentication are requested from the server and not the client, the machine in the middle can change the request to be the insecure variant.&lt;br /&gt;&lt;br /&gt;So of course the next level up is &lt;a href="http://en.wikipedia.org/wiki/HTTP_Secure"&gt;HTTPS&lt;/a&gt;, which does HTTP over &lt;a href="http://en.wikipedia.org/wiki/Transport_Layer_Security"&gt;SSL/TLS&lt;/a&gt;, which is supposed to provide end to end security, preventing man in the middle attacks. This level of security makes all those fiction stories fail in their plot. It also is supposed to keep us safe, and is used by websites for processing credit card information and other sensitive material.&lt;br /&gt;&lt;br /&gt;However, most users just type "something.muffin" into their browser, instead of prefixing it with http:// or https://, which will default to http://. Which again means the server has to initiate the secure connection. Since again this is also over a system which has both secure and insecure methods of communication, the same type of man in the middle attack as above can be performed.&lt;br /&gt;&lt;br /&gt;The following diagram illustrates it:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vLES3KKBdaM/SwwXvuMRpCI/AAAAAAAAAG8/ZM190luw1kQ/s1600/backandforth2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 296px;" src="http://2.bp.blogspot.com/_vLES3KKBdaM/SwwXvuMRpCI/AAAAAAAAAG8/ZM190luw1kQ/s320/backandforth2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5407723361185932322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Webservers are generally the one that initiates the redirection to an HTTPS page, which can be modified by the server in the middle. Any &lt;a href="http://en.wikipedia.org/wiki/Uniform_Resource_Locator"&gt;URL&lt;/a&gt; within a page which begins with https:// can be rewritten. For example, https://something.muffin can be changed to http://something.muffin:443 by an attacker in the middle, and then proceed with the attack as described above.&lt;br /&gt;&lt;br /&gt;Of course users should be looking for padlocks and green labels and similar in their browser, but how many do so? Since most sites people visit aren't running in secure environments, do you expect them to really notice when some page which is supposed to be secure isn't? Do you expect users to be savvy about security when most developers aren't?&lt;br /&gt;&lt;br /&gt;The amount of data which should be transferred securely but isn't is mind boggling. I see websites create a security token over HTTPS, but then pass that token around over HTTP, allowing anyone in the middle to steal it. I see people e-mail each other passwords to accounts on machines they manage all the time. I see database administrators login to phpMyAdmin running on servers with their root passwords sent in plain text. People working on projects together frequently send each other login credentials over forums or IRC in plain text.&lt;br /&gt;&lt;br /&gt;Anyone managing a hub somewhere on the vast internet should be able to log tons and tons of passwords. Once a password is gotten to someone's e-mail or forum account, then that can be scanned for even more passwords. Also, I see many users save root/admin passwords in plain text files on web servers, if one managed to get into their account by nabbing their password to it, they quite often will also be able to gain root by a simple scan of the user's files. Even if not, once access is gained to a machine, &lt;a href="http://en.wikipedia.org/wiki/Privilege_escalation"&gt;privilege escalation&lt;/a&gt; is usually the norm as opposed to the exception, because server administrators quite often do not keep up with security updates, or are afraid to alter a server that they finally got working.&lt;br /&gt;&lt;br /&gt;Careful pondering would show our entire infrastructure for communication is really a house of cards. It wouldn't be that hard for a small team with a bit of capital to setup free proxy servers around the world, offer free wi-fi at a bunch of hotspots, or start a small ISP. So the question we have to ask ourselves, is why are we still standing with everything in the shaky state it's in? I think the answer is simple, the malicious hackers really aren't out there. Sure there's hackers out there, and some of them do wreak a bit of havoc. But it seems no one is really interested in making trouble on a large scale.&lt;br /&gt;&lt;br /&gt;Mostly the hackers you hear about are people in a competition, or research, or those "security hackers", which have gone legit and want to help you secure your business. It's funny the amount of times I heard a story about how some bigwig at a company goes to some sort of computer expo, and runs across a table or booth of security "gurus". The bigwig asks how the security gurus can help his business, with the response asking if the bigwig owns a website. Once the bigwig mentions the name of his site, one guru pulls out his laptop and shows the bigwig the site with it defaced in some way. The bigwig panics and immediately hires them to do a whole load of nothing. Little does he realize he was just man-in-the-middle'd.</description><link>http://insanecoding.blogspot.com/2009/11/malicious-hackers-are-not-out-there.html</link><author>noreply@blogger.com (insane coder)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_vLES3KKBdaM/SwwXvXgGGzI/AAAAAAAAAG0/ukXR9RoDnc8/s72-c/backandforth1.png' height='72' width='72'/><thr:total>0</thr:total></item></channel></rss>