Archive

Posts Tagged ‘c++’

John 3:30 He must increase and I must decrease.

October 14th, 2013 1 comment
An interesting conversation that I’d lately picked with my beloved student and friend Gnana Sundar over facebook on John 3:30’s interpretation through a computer program snippet.

John 3:30 He must become greater and I must become lesser.

void john_3_30() {
jesus++;
self–;
}

Sudarsun Santhiappan: syntax error, unless instance variables “jesus” and “self” are globally defined (by who is a question you should answer). in some sense, you can also connect this relationship to holy trinity.

Gnana Sundar: Sir, did you check your class”path”? What “compiler” are you using?

Sudarsun Santhiappan: compiler” is analogous to the “religion”, which defines the book of rules for a good living (lifetime of the application). class”path” is analogous to the “help” that you get from other “runnable” wisdom in the “RunTime” called “life”.

Ulagammal Paramasivam: It shud be int john_3_30 as the return of this can’t be void.

Sudarsun Santhiappan: i would argue that the return type can only be a boolean (if at all), whether you attained sanity & solace or not. It cannot be a discrete or continuous evaluation as there is nothing to compare against. typically, add the line “return !self;”. does it make sense? The interpretation could be “have you given up yourself completely (to jesus, if you may add) ?”.

Gnana Sundar: Ulags: 🙂 …. I do not want to return from this method. I want this to run in an eternity loop 🙂

Sudarsun Santhiappan: Pragmatic Error: John 3:30 does not endorse one time ++ or –, it is an iterative process, if i may presume. Moreover, one time ++ or — is not a stable and a viable solution to minimization. Anything, that’s gradually minimized or maximized tend to be stable for better and longer. So, i would disagree to your point Gnana. 🙂

Gnana Sundar: Sir, I totally agree with you that John 3:30 does not endorse a one time ++ or –. It is a continuous process until eternity sets in. But I’m sure that the environment in which this is going to run is going to have infinite stack segment. If you say life is “RunTime”, the one who instantiated me would have to worry about stack overflow . When He can have the memory and a scalable enviroment to hold this universe and its contents, I’m pretty syre he can do better memory management and garbage collection

Just to give you some context. The Book of John is one of the four gospel books from the bible. It was written by John, one of the disciples of Christ.

In John 3:30, John the Baptist (he is not one of Jesus’ disciples, he is different from the author) says, “He must increase, but I must increase”. John the Baptist is considered to be a harbinger for Christ. He lived in the actual times when the Jews were “eagerly and for real” waiting for the Messiah. He had so many disciples and followers. He was considered to be a prophet. His calling in life was to prepare the way for Christ’ entry. When Christ started his ministry of healing people and teaching about the Kingdom of Righteousness, John had more followers than Christ. So pride and envy could have easily set in John. People, John’s disciples, John’s followers were eagerly waiting for John’s reaction. AT this point of time he uttered, its time… “He must increase and I must decrease” (thus the fulfilling the calling in his life).

In the same way when one accepts Christ in His heart, he/she should tune his/her heart and mind to say, “He must increase and I must decrease” and understand the actual calling and meaning of accepting Christ and their existence

By the way, I do not consider bible as a “religious” text. Religion limits the boundaries of this book and one’s life. It is open source . It is a set of God inspired writings, written by disciples for other disciples.

Sudarsun Santhiappan: Well said.

How fast is integer arithmetic than floating point arithmetic?

June 19th, 2013 No comments
You may already know that integer arithmetic is faster than floating point arithmetic. But how fast? I had the same question in my mind. So created the following script to test the “fastness” for each data type.

#include <vector>
#include <iostream>
#include <cstdlib>
#include “Stopwatch.hpp”

template <typename T>
void test( size_t inArraySize, size_t inCorpusSize )
{
    typedef std::vector<T> array_t;
    typedef std::vector<array_t> arrays_t;

    std::cout << “constructing the corpus…”;

    Stopwatch sw;
    sw.Start();
    arrays_t corpus( inCorpusSize + 1);
    for ( size_t i = 0; i < inCorpusSize+1; ++i )
    {
        array_t &array = corpus[i];
        array.resize( inArraySize );
        for ( size_t j = 0; j < inArraySize; ++j )
        {
            array[j] = (T)( rand() );
        }
    }

    sw.Stop();
    std::cout << sw.Elapsed() << ” secs” << std::endl;

    std::cout << “scored in … “;
    sw.Start();
    array_t scores( inCorpusSize );
    const array_t &query = corpus[0];
    for ( size_t i = 1; i < inCorpusSize+1; ++i )
    {
        const array_t &array = corpus[i];

        register T &score = scores[i1];
        score = 0;
        for ( size_t j = 0; j < inArraySize; ++j )
        {
            score += array[j]*query[j];
        }
    }

    sw.Stop();
    std::cout << sw.Elapsed() << ” secs” << std::endl;

}

int main( int argc, char **argv )
{
    if ( argc < 2 )
        return 1;

    int csize = atoi(argv[1]);
    int asize = atoi(argv[2]);

    std::cout << “testing float..” << std::endl;
    test<float>( asize, csize );

    std::cout << “testing double..” << std::endl;
    test<double>( asize, csize );

    std::cout << “testing long double..” << std::endl;
    test<long double>( asize, csize );

    std::cout << “testing int..” << std::endl;
    test<int>( asize, csize );

    std::cout << “testing unsigned int..” << std::endl;
    test<unsigned int>( asize, csize );

    std::cout << “testing short..” << std::endl;
    test<short>( asize, csize );

    std::cout << “testing unsigned short..” << std::endl;
    test<unsigned short>( asize, csize );

    std::cout << “testing char..” << std::endl;
    test<char>( asize, csize );

    std::cout << “testing unsigned char..” << std::endl;
    test<unsigned char>( asize, csize );

    std::cout << “testing long long..” << std::endl;
    test<long long>( asize, csize );

    std::cout << “testing unsigned long long..” << std::endl;
    test<unsigned long long>( asize, csize );

    return 0;
}

Syntax highlighting done by: /usr/bin/highlight -O html -t 4 -I -S cpp Main.cpp –inline-css -o /tmp/m.html

The result of running this script with vector size = 100 and corpus size = 1 million is shown below:
sudar@kiriya /opt/testing/bin $ ./tester 1000000 100
testing float..
constructing the corpus…1.447 secs
scored in … 1.731 secs

testing double..
constructing the corpus…1.543 secs
scored in … 1.836 secs

testing long double..
constructing the corpus…2.135 secs
scored in … 2.614 secs

testing int..
constructing the corpus…1.454 secs
scored in … 1.657 secs

testing unsigned int..
constructing the corpus…1.41 secs
scored in … 1.615 secs

testing short..
constructing the corpus…1.394 secs
scored in … 1.59 secs

testing unsigned short..
constructing the corpus…1.347 secs
scored in … 1.542 secs

testing char..
constructing the corpus…1.313 secs
scored in … 1.507 secs

testing unsigned char..
constructing the corpus…1.328 secs
scored in … 1.522 secs

testing long..
constructing the corpus…1.553 secs
scored in … 1.767 secs

testing unsigned long..
constructing the corpus…1.548 secs
scored in … 1.761 secs

  1. If you observe carefully, floating point calculations have taken more time than the fixed point calculations.
  2. Long Double took the longest time and it is the slowest.
  3. The reverse climax is that 64bit fixed calculation is slower than single-precision arithmetic.  An interesting read on multiplication is here.  The reason could be overflow due to the size of product register being 64 bits.
  4. The fastest is 8 bit calculation.  But unsigned 8 bit arithmetic is slower than signed.  Can’t explain why!
  5. For fixed point, unsigned calculations take less time than signed calculations, which can be understood by the additional time taken for 2’s complement arithmetic.
  6. Results can be different with different CPUs / Operating Systems, so infer accordingly.

Upgrade version of the testing application.
#include <vector>
#include <iostream>
#include <cstdlib>
#include “Stopwatch.hpp”
#include <string>
#include <map>

template <typename T>
double test( size_t inArraySize, size_t inCorpusSize )
{
     typedef std::vector<T> array_t;
     typedef std::vector<array_t> arrays_t;

     arrays_t corpus( 2 );
     for ( size_t i = 0; i < 2; ++i )
     {
          array_t &array = corpus[i];
          array.resize( inArraySize );
          for ( size_t j = 0; j < inArraySize; ++j )
          {
               array[j] = (T)( rand()%1000 );
          }
     }

     Stopwatch sw;
     sw.Start();
     const array_t &query = corpus[0];

     array_t scores( inCorpusSize );
     for ( register size_t i = 0; i < inCorpusSize; ++i )
     {
          const array_t &docu = corpus[1];
          T & score = scores[i];
          score = 0;
          for ( register size_t j = 0; j < inArraySize; ++j )
          {
               score += docu[j]*query[j];
          }
     }

     sw.Stop();
     return sw.Elapsed();
}

int main( int argc, char **argv )
{
     typedef double (*fun_t)( size_t, size_t );

     typedef std::pair < std::string, fun_t > named_fun_t;
     std::vector< named_fun_t > functions;

     functions.push_back( named_fun_t( “float”, test<float>) );
     functions.push_back( named_fun_t( “double”, test<double>) );
     functions.push_back( named_fun_t( “long double”, test<long double>) );
     functions.push_back( named_fun_t( “int”, test<int>) );
     functions.push_back( named_fun_t( “unsigned int”, test<unsigned int>) );
     functions.push_back( named_fun_t( “short”, test<short>) );
     functions.push_back( named_fun_t( “unsigned short”, test<unsigned short>) );
     functions.push_back( named_fun_t( “long long”, test<long long>) );
     functions.push_back( named_fun_t( “unsigned long long”, test<unsigned long long>) );
     functions.push_back( named_fun_t( “char”, test<char>) );
     functions.push_back( named_fun_t( “unsigned char”, test<unsigned char>) );

     if ( argc < 4 )
     {
          std::cout << argv[0] << ” <corpus_size> <array_size> <repeats>” << std::endl;
          return 1;
     }

     int csize = atoi(argv[1]);
     int asize = atoi(argv[2]);
     int iters = atoi(argv[3]);

     typedef std::map<std::string, double> timings_t;
     timings_t timings;

     for ( size_t j = 0; j < iters; ++j )
     {
          std::cout << \niteration #” << j+1 << std::endl;
          for ( size_t i = 0; i < functions.size(); ++i )
          {
               std::string name = functions[i].first;
               double timetaken = functions[i].second(asize, csize);

               timings[name] += timetaken;
               std::cout << “testing “ << name << “….” << timetaken << std::endl;
          }
     }

     std::string minstring;
     double minvalue = 99999.9;
     std::cout << \naverages” <<std::endl;
     for ( timings_t::iterator iter = timings.begin(), end = timings.end(); iter != end; ++iter )
     {
          iter->second /= (double)iters;
          std::cout << “average time for “ << iter->first << “: “ << iter->second << std::endl;

          if ( iter->second < minvalue )
          {
               minvalue = iter->second;
               minstring = iter->first;
          }
     }

     std::cout << “minimum timing is for “ << minstring << “: “ << minvalue << std::endl;
}

The result of running this script with vector size = 500 and corpus size = 1 million with 20 iterations is shown below:

iteration #1
testing float….1.473
testing double….1.469
testing long double….2.025
testing int….1.024
testing unsigned int….1.069
testing short….0.996
testing unsigned short….0.993
testing long long….1.004
testing unsigned long long….1.004
testing char….0.991
testing unsigned char….0.991

iteration #2
testing float….1.449
testing double….1.459
testing long double….2.011
testing int….1.002
testing unsigned int….1
testing short….0.985
testing unsigned short….0.99
testing long long….0.993
testing unsigned long long….0.993
testing char….0.983
testing unsigned char….0.992


..
iteration #20
testing float….1.448
testing double….1.45
testing long double….1.975
testing int….0.99
testing unsigned int….0.991
testing short….0.989
testing unsigned short….0.986
testing long long….0.997
testing unsigned long long….0.992
testing char….0.992
testing unsigned char….0.988

averages
average time for char: 0.99575
average time for double: 1.4665
average time for float: 1.4676
average time for int: 1.0046
average time for long double: 2.00115
average time for long long: 1.00585
average time for short: 0.99985
average time for unsigned char: 0.9945
average time for unsigned int: 1.0085
average time for unsigned long long: 1.0025
average time for unsigned short: 0.9963
minimum timing is for unsigned char: 0.9945

So, even in this test, char is the best choice!!

Hash Overflow due to 64 bit upcasting

October 28th, 2011 No comments
    Lately, I had to debug the following piece of code, where it caused overflow on the hash bucket design.  The code worked perfectly on a Windows machine while compiled for Win32, but failed to work on a Linux Mint x64 machine.  The code is listed below, which basically calculates hash value of an input 32 bit unsigned number, limiting the hash value to 2^10 (1Meg).

hash = ( fpArray*2654404609 )>>12; // Calculate the hash and limit the value to 2^20 (1 Meg)

   When the input value for fpArray was 1724463449 (0x66C93959), the hash value generated was 1779068547 (0x6A0A6E83), which is more than (0x000FFFFF) to cause the hash bucket overflow.

unsigned hash = fpArray * 2654404609;
hash = hash >> 12;

    When I rewrote the code like the above, the value of hash was 2800236889 (0xA6E83959).  Upon shifting right by 12 yields 638651 (0x0009BEBB), which is the correct and expected hash value.

    Overall, the first snippet of code appears to be correct.  Do you see a problem there?  I couldn’t find the issue, until I recalled the 32bit vs 64bit difference.  If you carefully look at the multiplier 2654404609 (0x9E370001), although appears to be a valid 32 bit number, what is the default assignment of type to this number by the compiler?  If it was assigned 64bits, what would happen to the results?  To validate this, I changed the 2nd snippet as the following.

unsigned long hash = (unsigned long)fpArray * 2654404609;
hash = hash >> 12;
unsigned h2 = (unsigned)hash;

    Now, when the input is the same 1724463449 (0x66C93959), the value of hash becomes 4577423727077636441 (0x3F8646A0A6E83959) and upon right shifting by 12 bits yields 1117535089618563 (0x0003F8646A0A6E83). Followed by downcasting to unsigned yield 1779068547 (0x6A0A6E83). Bingo!

    So, what is happening here? While performing (fpArray * 2654404609), the computation is upcasted to 64bit computation by the 64 bit compiler.  So, what is the solution? Just put a “U” at the end of the constant.

hash = ( fpArray*2654404609U )>>12; // Calculate the hash and limit the value to 2^20 (1 Meg)
(or)
const unsigned multipler = 2654404609; // here U suffix is not needed as the constant is explicitly made unsigned
hash = ( fpArray * multiplier ) >> 12;

    Now, the computation will happen with 32 bit numbers to get the expected outputs.

Lessons Learned here:

  1. While using constants, beware of the upcasting and downcasting. So use proper suffixes like U, L, F etc.
  2. Instead of using constants directly in expressions, use them as constant variables.
  3. Be conscious about the compiler type and the assumptions made by the compiler in different build modes.

no include path in which to search for limits.h

June 16th, 2011 No comments

Why compiling STLport 5.1.5 using g++-4.4, one might get an error like the following:-

Building CXX object libs/bgt/CMakeFiles/bgt.dir/error.o
In file included from /opt/projects/stl/stlport/limits.h:27,
            from /usr/include/c++/4.4/../4.4.5/climits:43,
            from /opt/projects/stl/stlport/climits:27,
            from /opt/projects/stl/stlport/stl/_algobase.h:42,
            from /opt/projects/stl/stlport/stl/_alloc.h:47,
            from /opt/projects/stl/stlport/stl/_string.h:23,
            from /opt/projects/stl/stlport/stl/_ios_base.h:34,
            from /opt/projects/stl/stlport/stl/_ios.h:23,
            from /opt/projects/stl/stlport/stl/_ostream.h:24,
            from /opt/projects/stl/stlport/ostream:31,
            from /opt/projects/dev/libs/bgt/error.cpp:18:
/usr/include/../include/limits.h:125: error: no include path in which to search for limits.h
In file included from /opt/projects/stl/stlport/stl/_num_put.c:26,
            from /opt/projects/stl/stlport/stl/_num_put.h:183,
            from /opt/projects/stl/stlport/stl/_ostream.c:26,
            from /opt/projects/stl/stlport/stl/_ostream.h:380,
            from /opt/projects/stl/stlport/ostream:31,
            from /opt/projects/dev/libs/bgt/error.cpp:18:
/opt/projects/stl/stlport/stl/_limits.h:148: error: ‘CHAR_BIT’ was not declared in this scope
/opt/projects/stl/stlport/stl/_limits.h:253: error: ‘CHAR_MIN’ was not declared in this scope
..

Looks like it is a bug in the STLport package itself as per the Release notes of STLport.  After updating to STLport-5.2.1, the issue got fixed automatically.

MongoDB C++ Wrapper

April 3rd, 2011 No comments

MongoDB has drivers in almost all language.  Being a C++ programmer,  although there is a C++ driver, I am stinged to see that the driver cannot be used with STLport.  The reason being, C++ MongoDB driver is compiled with Boost, which does not go well with STLport.  I could link my application in Release mode, but debug mode would not work.  Also, Boost says that STLport is not uniform across platforms, they don’t support STLport for linux platforms.

So, I am left out with only one option; that is to create a C++ driver myself.  I found the C driver working excellently (although there are design glitches!).  I am currently developing a C++ wrapper around the C driver to support fundamental operations on Mongo from an application compiled with STLport in C++ and cross platform.

First Application using MongoDB & PHP

March 6th, 2011 No comments
I have been eyeing on MongoDB since I had visited IIIT Hyderabad for campus placements in Jan 2011.  The name MongoDB was introduced to me by the candidates whom I had to interview.  Infact all the candidates who took the interview had worked on MongoDB for solving some problem during their graduate studies.   MongoDB, the name comes from HuMongous DataBase, which is a well instituted name and the database indeed is meant for storing tonnes of data organized in JSON format.   Being a C++ coder, I had less experience with JSON and have always avoided that as it was primarily used in the Web application development.  After learning about Mongo in the official wiki, I got thrilled by the simplicity of JSON format and the advantage of it over the conventional XML format and infact decided to use JSON for a project that my team is working on.
MongoDB is written in C++, which increased my love towards the database.  I wanted to use MongoDB for my product development data store needs, but was stuck with the dependencies of Mongo’s C++ driver, where it wanted Boost libraries to be linked.  The pathetic problem is boost does not compile with the debug version of STLport.  My product is built on STLport, so I have to link MongoDB with Boost/STLport, which works well in release mode, but not in DEBUG mode.  How Sad!
My desperation grew as I wanted to have some useful application developed using MongoDB.  PHP came for my rescue. The PHP driver that was available with MongoDB is a cute baby.   I works like moon walk, when copy pasted on the PHP’s extension folder.   The documentation of PHP/MongoDB is well written and has lot of examples.  Also, there is awesome support available in the internet for all the doubts that I got while building my Brower based Photo SlideShow web application.  All, I did was, I pushed all my JPEG files into MongoDB and wrote simple PHP scripts to fetch the files based on the file name.  When the file name was not mentioned, my script would pick a file randomly.  I have presented the code below:
# view.php

# get the file id
$id = "";
if ( array_key_exists( "id", $_REQUEST ) ) {
    $id = $_REQUEST["id"];
}

# open database connectivity
$conn = new Mongo();
$store = $conn->store;
$image = $store->image;

# fetch the file as per the id or just randomly
if ( $id != "" ) {
    $query = array ( 'id' => $id );
    $cursor = $image->find( $query );
}
else {
    # set the html headers for refreshing the page every 3 sec.
    header( 'Refresh: 3;' );

    # Random fetch logic, get the count first.
    $count = $image->find()->count();
    $rand = rand( 1, $count-1 );  # generate a random number.
    # skip several records of the cursor based on the random number
    $cursor = $image->find()->skip( $rand )->limit(1);  
}

# write output stream as JPEG content
header( 'Content-Type: image/jpeg' );
foreach ( $cursor as $obj ) {
    # decode the data, and just write on the output stream.
    echo base64_decode($obj["data"]);
}

# import.php

$dir = $_REQUEST["dir"];
if ( $dir == "" ) {
    echo "<h2>Import directory cannot be empty</h2>";
    exit;
}

$conn = new Mongo();
$db = $conn->store;
$image = $db->image;

echo "<ol>";
$dhandle = opendir( $dir );
while ( ($file = readdir( $dhandle )) != false ) {
    $path = $dir."/".$file;
    if ( is_dir( $path ) ) {
        continue;
    }

    $path = str_replace( '\\', '/', $path );
    $handle = fopen( $path, "rb" );
    $data = fread( $handle, filesize( $path ) );
    fclose( $handle );
    if ( $data == false ) {
	continue;
    }

    $key = preg_replace( "/[[:punct:]]/", "_", $file );
    echo "<li>Importing $path (Key: $key)...";
    try {
        $image->insert( array( "id" => $key, 
               "data" => base64_encode( $data ) ), true );
        echo "Success";
    }
    catch ( MongoCursorException $e ) {
        echo "Exception: $e";
    }
	
    echo "</li>";
    ob_flush();
}

echo "</ol>";

Within minutes, I was able to have a browser based slide show application, which protected all my image files in the Database without being exposed out in the folder system.

I am enjoying every bit of Mongo, and hope to develop several application using that in the future.

ACE 5.6.7 does not compile with STLport in Win32 environment

June 14th, 2010 No comments

ACE 5.6.7 does not compile with STLport in Windows environment (I used vc9 on Windows Server 2008) because of the following header in ACE (ACE_wrappers/ace/checked_iterator.h), which wrongly assumes the existence of stdext::checked_array_iterator in the iterator header.  A PRF is already submitted in the ACE mailing list (http://www.archivum.info/comp.soft-sys.ace/2008-07/00026/%5Bace-users%5D-Checked_iterator.h-problem-with-STLport..html)

# if defined (_MSC_VER) && (_MSC_FULL_VER >= 140050000)
// Checked iterators are currently only supported in MSVC++ 8 or better.
#  include <iterator>
# endif  /* _MSC_VER >= 1400 */

# if defined (_MSC_VER) && (_MSC_FULL_VER >= 140050000)
template <typename PTR>
stdext::checked_array_iterator<PTR>
ACE_make_checked_array_iterator (PTR buf, size_t len)
{
return stdext::checked_array_iterator (buf, len);
}
# else
template <typename PTR>
PTR
ACE_make_checked_array_iterator (PTR buf, size_t /* len */)
{
// Checked iterators are unsupported.  Just return the pointer to
// the buffer itself.
return buf;
}
# endif  /* _MSC_VER >= 1400 */

#endif  /* ACE_CHECKED_ITERATOR_H */

I need to develop a solution to it.  The easiest way to find a solution is to use some macro explicitly set by the STLport header, which is not set by any other STL libraries.  I chose to use the _STLP_ITERATOR macro set by “stl/stlport/iterator” header.

#ifndef _STLP_ITERATOR
#define _STLP_ITERATOR

# ifndef _STLP_OUTERMOST_HEADER_ID
#  define _STLP_OUTERMOST_HEADER_ID 0x38
#  include <stl/_prolog.h>
# endif

# ifdef _STLP_PRAGMA_ONCE
#  pragma once
# endif

#if defined (_STLP_IMPORT_VENDOR_STD)
# include _STLP_NATIVE_HEADER(iterator)
#endif /* IMPORT */

# ifndef _STLP_INTERNAL_ITERATOR_H
#  include <stl/_iterator.h>
# endif

# ifndef _STLP_INTERNAL_STREAM_ITERATOR_H
#  include <stl/_stream_iterator.h>
# endif

# if (_STLP_OUTERMOST_HEADER_ID == 0x38)
#  include <stl/_epilog.h>
#  undef _STLP_OUTERMOST_HEADER_ID
# endif

#endif /* _STLP_ITERATOR */

The solution is the following, where I have added the !defined(_STLP_ITERATOR) condition along with the check for Visual Studio compiler version.

# if !defined(_STLP_ITERATOR) && defined (_MSC_VER) && (_MSC_FULL_VER >= 140050000)
// Checked iterators are currently only supported in MSVC++ 8 or better.
#  include <iterator>
# endif  /* _MSC_VER >= 1400 */

# if defined (_MSC_VER) && (_MSC_FULL_VER >= 140050000)
template <typename PTR>
stdext::checked_array_iterator <PTR>
ACE_make_checked_array_iterator (PTR buf, size_t len)
{
return stdext::checked_array_iterator (buf, len);
}
# else
template <typename PTR>
PTR
ACE_make_checked_array_iterator (PTR buf, size_t /* len */)
{
// Checked iterators are unsupported. Just return the pointer to
// the buffer itself.
return buf;
}
#
endif  /* _MSC_VER >= 1400 */

#endif
/* ACE_CHECKED_ITERATOR_H */

Compile 32bit C/C++ Application in 64bit Linux

October 8th, 2009 No comments

To build (cross compilation) 32 bit C/C++ applications on 64 bit linux box, use “-m32” as a compiler argument.  You would need the following 32bit libraries in place.

  1. Install glibc.i386, glibc-devel.i386
  2. Install libgcc.i386
  3. Install libstdc++.i386

#include <cstdio>
#include <iostream>
main()
{
    std::cout << “C++” << std::endl;
    printf ( “long: %d\n”, sizeof(long) );
    printf ( “long long: %d\n”, sizeof(long long) );
    return 0;
}

To compile in native 64bit:
[sudar@tstsrv12 tmp]$ g++ -m64 -o out64 code.cpp

[sudar@tstsrv12 tmp]$ ./out64
C++
long: 8
long long: 8

[sudar@tstsrv12 tmp]$ ldd out64
        linux-vdso.so.1 =>  (0x00007fffc43fe000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003e7be00000)
        libm.so.6 => /lib64/libm.so.6 (0x0000000000601000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003e79e00000)
        libc.so.6 => /lib64/libc.so.6 (0x0000000000886000)
        /lib64/ld-linux-x86-64.so.2 (0x0000000000110000)

To compile in 32bit:
[sudar@tstsrv12 tmp]$ g++ -m32 -o out32 code.cpp

[sudar@tstsrv12 tmp]$ ./out32
C++
long: 4
long long: 8

[sudar@tstsrv12 tmp]$ ldd out32
        linux-gate.so.1 =>  (0x00130000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00133000)
        libm.so.6 => /lib/libm.so.6 (0x00223000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x0024c000)
        libc.so.6 => /lib/libc.so.6 (0x0025a000)
        /lib/ld-linux.so.2 (0x00110000)

Get MAC address using C++

July 4th, 2009 No comments

There is a Simple way to capture the MAC address of the machine in Win32 environment. In Win32, UUID (version 1) uses MAC address & timestamp as the seeds for generating the UUID.  In the UUID string, the last 6 bytes are the MAC address of the machine.  UuidCreateSequential() is the Win32 API which is used to capture the MAC address via the UUID generated by it.

#include <rpc.h>      // for UUID, UuidCreateSequential
#include <cstring>    // for memcpy
#include <algorithm>  // for std::swap

unsigned __int64
MACAddress( void ) const
{
    UUID u;
    ::UuidCreateSequential( &u );

    u.Data4[0] = u.Data4[1] = 0;

    std::swap( u.Data4[0], u.Data4[7] );
    std::swap( u.Data4[1], u.Data4[6] );
    std::swap( u.Data4[2], u.Data4[5] );
    std::swap( u.Data4[3], u.Data4[4] );

    unsigned __int64 code;
    ::memcpy( &code, &u.Data4, sizeof(u.Data4) );

    return code;
}   // MACAddress

Let me share another hack. If you want to generate strings which do not repeat themselves, you could use UuidCreate() Win32 API, which generates unique UUIDs everytime the function is called.  The UUID thus obtained can be converted to a number or a string depending upon the need, which guarantees non-repeatable ids.

Error: Can not start thread: error writing TLS. (error 87: the parameter is incorrect.)

February 18th, 2009 No comments

When I tried building an multi-thread TUI application using wxWidgets framework, I got the following error while executing the application.

Error: Can not start thread: error writing TLS. (error 87: the parameter is incorrect.)

I was not able to reason out this behavior. I tried changing between THREAD_DETACHABLE and THREAD_JOINABLE, but was not able to get through.  When I search for hints from the web, I got the following link.

http://osdir.com/ml/lib.wxwindows.general/2004-01/msg00759.html

It was advised to create a dummy wxInitializer object so that the wxWidgets platform does the necessary initialization.  wxInitializer class is an undocumented class and called internally when a wxFrame or wxDialog based GUI application is built.  Typically, wxInitializer object is instantiated internally by the wxApp class.  Since, in my application there is no wxApp object which led to the above problem

When I dug the declaration of wxInitializer class, I found it declared at wx/init.h;  Also I found that instead of instantiating the object, we may call the following function.

extern bool WXDLLIMPEXP_BASE wxInitialize(int argc = 0, wxChar **argv = NULL);

In my application, I did the following:

main( int argc, char **argv )
{
      extern bool wxInitialize( int, char ** );
      wxInitialize( argc, argv );
      ….
      ….
}

It worked like piece of cream.

Powered by ScribeFire.