I am tracking down some segfaults that may be related to the Program Options library. I've done my best to narrow the focus of what I'm doing and seeing. Now I'll report the results and see if anyone can help me get to the bottom of the issue.
Overview: Two C++ projects, a library (LIB) and an app (APP). Both developed in OpenSuse 11.3 using gcc45 and boost 1_45. Both built using CMake(makefiles), and share the same boost settings in a shared cmake file (settings listed later.) LIB is linked into APP (either staticly or dynamically , as discussed later.)
Both LIB and APP contain a options[Lib|App].cpp file that defines an uniquely named options global object. These objects store the option values as members and have a ParseOptions() method that use the Boost Program Options features. There is an exported API call in LIB that passes a string into the optionsLib object.
Now I'll start listing some known facts about how/when segfaults are seen.
1: Crashes never occur in Windows (using VC++10).
2: If everything is linked statically, there is never a segfault. (There are three linkages in question: APP->Boost, LIB->Boost, APP->LIB)
3: If everything is linked
dynamically there is never a segfault.
4: Segfaults occur when APP->LIB is dynamic while APP->Boost and LIB->Boost are linked statically.
This situation occurs even if a global options object in APP is never instantiated (but the options.cpp is still a part of the project)
It seems that the segfault occurs in the exit handlers. I posted some of a gdb session that shows some of the exit functions that are called.
*************************************************************
Here are the settings in CMake for the segfault situation:
set (Boost_ADDITIONAL_VERSIONS "1.46" "1.46.0" "1.45" "1.45.0" "1.44" "1.44.0" "1.43" "1.43.0")
set (Boost_USE_MULTITHREADED ON)
set (Boost_USE_STATIC_LIBS ON)
set (Boost_USE_STATIC_RUNTIME OFF)
find_package( Boost 1.41.0 COMPONENTS "program_options" "filesystem" "system")
*************************************************************
Here's the way that boost::po is used
#note that things like loggins have been stripped out
int AppOptions::ParseOptions(std::vector<std::basic_string<char> > optionsStrings )
{
try
{
// Declare a group of options that will be
// allowed only on command line
po::options_description generic("Generic options");
generic.add_options()
("version,v", "Print version string")
("help", "Produce help message")
("config-file,c", po::value<string>(&configFileName_)->default_value(configFileName_),
"Name of a file for configuration.")
;
#pragma warning( push )
#ifdef _WINDOWS
#pragma warning( disable : 4505 )
#endif
// Declare a group of options that will be
// allowed both on command line and in
// config file
po::options_description config("Configuration");
config.add_options()
("energy-dir,e",
po::value< string >(&energyDir_)->default_value(energyDir_),
"Path containing energy files")
("run-example",
po::bool_switch(&runExample_),
"Use example file (./example_input.txt) instead of stdin for input.")
("old-output-format",
po::bool_switch(&useOldOutputFormat_),
"Generate output in the old format, for compatibility reasons")
;
#pragma warning( pop )
po::options_description cmdline_options;
cmdline_options.add(generic).add(config);
po::options_description config_file_options;
config_file_options.add(config);
po::options_description visible("Allowed options");
visible.add(generic).add(config);
po::variables_map vm;
po::parsed_options options = po::command_line_parser(optionsStrings).
options(cmdline_options).allow_unregistered().run();
store(options, vm);
notify(vm);
std::stringstream ss;
ss << "App cmd-line options (plus defaults): " << std::endl;;
ss << "\t" << "config_file=" << configFileName_ << std::endl;
ss << "\t" << "energy-dir=" << energyDir_ << std::endl;
ss << "\t" << "run-example=" << runExample_ << std::endl;
ss << "\t" << "old-output-format=" << useOldOutputFormat_<< std::endl;
// pantheios::log_DEBUG( EX_PREFIX, "Config : ", ss.str().c_str() );
std::vector<string> to_pass_further = po::collect_unrecognized(options.options, po::exclude_positional);
if (configFileName_.size())
{
std::ifstream ifs(configFileName_.c_str());
if (!ifs)
{
std::stringstream ss;
ss << "can not open config file: " << configFileName_ << std::endl;;
ss << "creating default config file: " << configFileName_ << std::endl;;
// pantheios::log_DEBUG( EX_PREFIX, "Config file error: ", ss.str().c_str() );
std::ofstream ofs(configFileName_.c_str());
ofs << "energy-dir = SET/LOCATION/TO/ENERGY/FILES" << std::endl;
ofs.close();
return 1;
}
else
{
po::parsed_options file_options = parse_config_file(ifs, config_file_options);
store(file_options, vm);
notify(vm);
std::stringstream ss;
ss << "App post config-file options: " << std::endl;;
ss << "\t" << "config_file=" << configFileName_ << std::endl;
ss << "\t" << "energy-dir=" << energyDir_ << std::endl;
ss << "\t" << "run-example=" << runExample_ << std::endl;
ss << "\t" << "old-output-format=" << useOldOutputFormat_<< std::endl;
// pantheios::log_DEBUG( EX_PREFIX, "Config : ", ss.str().c_str() );
}
}
if (vm.count("help"))
{
std::cout << visible << "\n";
to_pass_further.push_back( "--help");
return 1;
}
if (vm.count("version"))
{
std::cout << "App version " << APP_FULL_VERSION << std::endl ;
return 1;
}
}
catch(std::exception const & e)
{
std::stringstream ss;
ss << "Configuration exception: " << e.what() << std::endl;
// pantheios::log_DEBUG( EX_PREFIX, "", ss.str().c_str() );
return 1;
}
return 0;
}
*************************************************************
gdb session
Breakpoint 2, __run_exit_handlers (status=0, listp=0xb7ca2304, run_list_atexit=true) at exit.c:78
(gdb) step
(gdb) next
(gdb) step
std::ios_base::Init::~Init (this=0x80da45c, __in_chrg=<value optimized out>) at ../../../../libstdc++-v3/src/ios_init.cc:123
(gdb) cont
Continuing.
Breakpoint 2, __run_exit_handlers (status=0, listp=0xb7ca2304, run_list_atexit=true) at exit.c:78
(gdb) step
(gdb) next
(gdb) step
std::ios_base::Init::~Init (this=0x80da46d, __in_chrg=<value optimized out>) at ../../../../libstdc++-v3/src/ios_init.cc:123
(gdb) cont
Continuing.
Breakpoint 2, __run_exit_handlers (status=0, listp=0xb7ca2304, run_list_atexit=true) at exit.c:78
(gdb) step
(gdb) next
(gdb) step
(gdb) cont
Continuing.
Breakpoint 2, __run_exit_handlers (status=0, listp=0xb7ca2304, run_list_atexit=true) at exit.c:78
(gdb) step
(gdb) next
(gdb) step
boost::program_options::detail::utf8_codecvt_facet::~utf8_codecvt_facet (this=0x80da4c4, __in_chrg=<value optimized out>) at ./boost/detail/utf8_codecvt_facet.hpp:108
(gdb) cont
Continuing.
Breakpoint 2, __run_exit_handlers (status=0, listp=0xb7ca2304, run_list_atexit=true) at exit.c:78
(gdb) step
(gdb) next
(gdb) step
std::ios_base::Init::~Init (this=0x80da4b8, __in_chrg=<value optimized out>) at ../../../../libstdc++-v3/src/ios_init.cc:123
(gdb) cont
Continuing.
Breakpoint 2, __run_exit_handlers (status=0, listp=0xb7ca2304, run_list_atexit=true) at exit.c:78
(gdb) step
(gdb) next
(gdb) step
std::ios_base::Init::~Init (this=0x80da4d0, __in_chrg=<value optimized out>) at ../../../../libstdc++-v3/src/ios_init.cc:123
(gdb) cont
Continuing.
Breakpoint 2, __run_exit_handlers (status=0, listp=0xb7ca2304, run_list_atexit=true) at exit.c:78
(gdb) step
(gdb) next
(gdb) step
__pthread_mutex_lock (mutex=0xb7fff4e4) at pthread_mutex_lock.c:47
(gdb) cont
Continuing.
*** glibc detected *** /home/turkey/PT-6/APP: double free or corruption (fasttop): 0x080dca38 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6dffb)[0xb7ba8ffb]
/lib/libc.so.6(+0x6ed7b)[0xb7ba9d7b]
/lib/libc.so.6(cfree+0x6d)[0xb7badadd]
/usr/lib/libstdc++.so.6(_ZdlPv+0x1f)[0xb7da198f]
/usr/lib/libstdc++.so.6(_ZNSs4_Rep10_M_destroyERKSaIcE+0x1b)[0xb7d8205b]
/usr/lib/libstdc++.so.6(_ZNSsD1Ev+0x4a)[0xb7d8210a]
/lib/libc.so.6(__cxa_finalize+0xab)[0xb7b69b4b]
/home/turkey/OC-6/libLIB22.so(+0xf9e74)[0xb7ed8e74]
/home/turkey/OC-6/libLIB22.so(+0x176b90)[0xb7f55b90]
/lib/ld-linux.so.2(+0xed1d)[0xb7fedd1d]
/lib/libc.so.6(+0x2e7cf)[0xb7b697cf]
======= Memory map: ========
08048000-080d9000 r-xp 00000000 fd:00 264869 /home/turkey/PT-6/APP
080d9000-080da000 r--p 00090000 fd:00 264869 /home/turkey/PT-6/APP
080da000-080db000 rw-p 00091000 fd:00 264869 /home/turkey/PT-6/APP
080db000-080fc000 rw-p 00000000 00:00 0 [heap]
b7900000-b7921000 rw-p 00000000 00:00 0
b7921000-b7a00000 ---p 00000000 00:00 0
b7af7000-b7af9000 r-xp 00000000 fd:01 6992 /usr/lib/gconv/ISO8859-1.so
b7af9000-b7afa000 r--p 00001000 fd:01 6992 /usr/lib/gconv/ISO8859-1.so
b7afa000-b7afb000 rw-p 00002000 fd:01 6992 /usr/lib/gconv/ISO8859-1.so
b7afb000-b7b02000 r--s 00000000 fd:01 7064 /usr/lib/gconv/gconv-modules.cache
b7b02000-b7b39000 r--p 00000000 fd:01 7759 /usr/lib/locale/en_US/LC_CTYPE
b7b39000-b7b3b000 rw-p 00000000 00:00 0
b7b3b000-b7c9f000 r-xp 00000000 fd:01 158 /lib/libc-2.11.2.so
b7c9f000-b7ca0000 ---p 00164000 fd:01 158 /lib/libc-2.11.2.so
b7ca0000-b7ca2000 r--p 00164000 fd:01 158 /lib/libc-2.11.2.so
b7ca2000-b7ca3000 rw-p 00166000 fd:01 158 /lib/libc-2.11.2.so
b7ca3000-b7ca6000 rw-p 00000000 00:00 0
b7ca6000-b7cc2000 r-xp 00000000 fd:01 249 /lib/libgcc_s.so.1
b7cc2000-b7cc3000 r--p 0001b000 fd:01 249 /lib/libgcc_s.so.1
b7cc3000-b7cc4000 rw-p 0001c000 fd:01 249 /lib/libgcc_s.so.1
b7cc4000-b7cc5000 rw-p 00000000 00:00 0
b7cc5000-b7ced000 r-xp 00000000 fd:01 243 /lib/libm-2.11.2.so
b7ced000-b7cee000 r--p 00027000 fd:01 243 /lib/libm-2.11.2.so
b7cee000-b7cef000 rw-p 00028000 fd:01 243 /lib/libm-2.11.2.so
b7cef000-b7dd3000 r-xp 00000000 fd:01 6775 /usr/lib/libstdc++.so.6.0.14
b7dd3000-b7dd7000 r--p 000e3000 fd:01 6775 /usr/lib/libstdc++.so.6.0.14
b7dd7000-b7dd8000 rw-p 000e7000 fd:01 6775 /usr/lib/libstdc++.so.6.0.14
b7dd8000-b7ddf000 rw-p 00000000 00:00 0
b7ddf000-b7fa8000 r-xp 00000000 fd:00 305471 /home/turkey/OC-6/libLIB22.so
b7fa8000-b7faa000 r--p 001c8000 fd:00 305471 /home/turkey/OC-6/libLIB22.so
b7faa000-b7faf000 rw-p 001ca000 fd:00 305471 /home/turkey/OC-6/libLIB22.so
b7faf000-b7fb0000 rw-p 00000000 00:00 0
b7fb0000-b7fc7000 r-xp 00000000 fd:01 183 /lib/libpthread-2.11.2.so
b7fc7000-b7fc8000 r--p 00016000 fd:01 183 /lib/libpthread-2.11.2.so
b7fc8000-b7fc9000 rw-p 00017000 fd:01 183 /lib/libpthread-2.11.2.so
b7fc9000-b7fcb000 rw-p 00000000 00:00 0
b7fcf000-b7fd0000 r--p 00000000 fd:01 131840 /usr/lib/locale/en_US/LC_IDENTIFICATION
b7fd0000-b7fd1000 r--p 00000000 fd:01 131586 /usr/lib/locale/en_US/LC_MEASUREMENT
b7fd1000-b7fd2000 r--p 00000000 fd:01 8241 /usr/lib/locale/en_US/LC_TELEPHONE
b7fd2000-b7fd3000 r--p 00000000 fd:01 131842 /usr/lib/locale/en_US/LC_ADDRESS
b7fd3000-b7fd4000 r--p 00000000 fd:01 8242 /usr/lib/locale/en_US/LC_NAME
b7fd4000-b7fd5000 r--p 00000000 fd:01 8245 /usr/lib/locale/en_US/LC_PAPER
b7fd5000-b7fd6000 r--p 00000000 fd:01 8240 /usr/lib/locale/en_US/LC_MESSAGES/SYS_LC_MESSAGES
b7fd6000-b7fd7000 r--p 00000000 fd:01 131838 /usr/lib/locale/en_US/LC_MONETARY
b7fd7000-b7fdc000 r--p 00000000 fd:01 7761 /usr/lib/locale/en_US/LC_COLLATE
b7fdc000-b7fdd000 r--p 00000000 fd:01 131839 /usr/lib/locale/en_US/LC_TIME
b7fdd000-b7fde000 r--p 00000000 fd:01 7927 /usr/lib/locale/en_US/LC_NUMERIC
b7fde000-b7fdf000 rw-p 00000000 00:00 0
b7fdf000-b7ffe000 r-xp 00000000 fd:01 296 /lib/ld-2.11.2.so
b7ffe000-b7fff000 r--p 0001e000 fd:01 296 /lib/ld-2.11.2.so
b7fff000-b8000000 rw-p 0001f000 fd:01 296 /lib/ld-2.11.2.so
bffdf000-c0000000 rw-p 00000000 00:00 0 [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
Program received signal SIGABRT, Aborted.
0xffffe424 in __kernel_vsyscall ()
Thanks for any help in determining if the crash is caused by me or not.
Keith