Thursday, January 14, 2010

ls using boost

Want to use boost and get list of files matching a mask. The same list you would obtain running ls in the command prompt?

The idea is to have something like this:


BOOST_FOREACH( const std::string& fname, ls( "./*.cpp" ))
std::cout << fname << std::endl ;


So here is the solution. One function and one helper function (to_regex_copy()):


std::string to_regex_copy( std::string mask )
{
std::string rv = boost::regex_replace( boost::regex_replace( boost::regex_replace( mask, boost::regex( "\\." ), "\\\\." ), boost::regex( "\\?" ), "\\." ), boost::regex( "\\*" ), "\\.*" ) ;
return rv ;
}

std::vector< std::string > ls( const char* pcszMask )
{
namespace fs = boost::filesystem ;
boost::filesystem::path path ;
boost::regex mask ;
if ( fs::is_directory( pcszMask ))
{
path = pcszMask ;
mask = ".*" ;
}
else
{
path = fs::path( pcszMask ).remove_filename() ;
mask = to_regex_copy( fs::path( pcszMask ).filename()) ;
}

std::vector< std::string > rv ;
try
{
for ( fs::directory_iterator p(path), e; p!=e; ++p)
{
if ( boost::regex_match( p->filename(), mask ))
rv.push_back( p->filename()) ;
}
}
catch( ... )
{
}

return rv ;
}

Tuesday, January 12, 2010

Profiling shared library on Linux using sprof

It's not as easy as one would/should expect. (Read here about valgrind if you don't want to use sprof.)

First - FORGET ABOUT gprof. gprof is used for the applications but will NOT WORK for shared libraries. Sorry about that. I learned about it the hard way. What you need to use is sprof.

Second - sprof may make you bite your fingers if your glibc library is not up-to-date. It will be displaying the nasty message: "sprof: failed to load shared object"
If this is what you see then you HAVE TO update your glibc. Read about the bug: here. It may not be as simple to upgrade as well... If I have time I will write how to do it through the .iso file (if you have one.)

Third - Yes, as it is not enough, there is an other surprize! The -pg option works well for gprof, but screws up things for sprof! You need to remove this option in order to get proper results from the shared libraries. Otherwise you will get only zeroes as the execution time for the functions.

So, at the end, what to do?

Assuming you have the patch installed or you have glibc-2.5-34 or newer version installed do as follows (the best, in my opinion, way, assuming you have write access to the current directory.)

1) Compile your shared library (libmylib.so) in debug (-g) mode. No -pg.
2) export LD_PROFILE_OUTPUT=`pwd`
3) export LD_PROFILE=libmylib.so
4) rm -f $LD_PROFILE.profile
4) execute your program that loads libmylib.so
5) sprof PATH-TO-LIB/$LD_PROFILE $LD_PROFILE.profile -p >log
6) See the log.

I hope it will help you.