Problem with releasing RHEL4 using boost 1.36 and C ++

I'm struggling with a mysterious problem. I only see my RHEL4 build. Some of my unit tests (using boost 1.36 unit test framework) fail on RHEL4 (gcc 3.4.6) and use release build type. I do not see a problem using RHEL5 versions for release or debugging (gcc 4.1.2, boost-1.39); and I don't see it on Windows 32-bit or 64-bit using Visual Studio 2005 (using boost-1.36) or 2008 (using boost-1.39).

Suspecting that this might be due to some subtle memory issue, I continued to run valgrind in a test application (the smallest case that saved the problem). Here is what I got when I ran valgrind using the "full, inaccessible" mode:

==12285== Memcheck, a memory error detector. ==12285== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al. ==12285== Using LibVEX rev 1575, a library for dynamic binary translation. ==12285== Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP. ==12285== Using valgrind-3.1.1, a dynamic binary instrumentation framework. ==12285== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al. ==12285== For more details, rerun with: -v ==12285== ==12285== My PID = 12285, parent PID = 12284. Prog and args are: ==12285== ./myprojd ==12285== ==12285== Syscall param sigaltstack(ss) points to uninitialised byte(s) ==12285== at 0x3AD682EDA9: sigaltstack (in /lib64/tls/libc-2.3.4.so) ==12285== by 0x6488638: boost::detail::signal_handler::~signal_handler() (in /<path_to>/libboost_unit_test_framework-gcc34-mt-1_36.so.1.36.0) ==12285== by 0x648975E: boost::execution_monitor::catch_signals (boost::unit_test::callback0<int> const&) (in /<path_to>/libboost_unit_test_framework-gcc34-mt-1_36.so.1.36.0) ==12285== by 0x6489813: boost::execution_monitor::execute (boost::unit_test::callback0<int> const&) (in /<path_to>/libboost_unit_test_framework-gcc34-mt-1_36.so.1.36.0) ==12285== by 0x648F2E4: boost::unit_test::framework::run(unsigned long, bool) (in /<path_to>/libboost_unit_test_framework-gcc34-mt-1_36.so.1.36.0) ==12285== by 0x649BD02: boost::unit_test::unit_test_main(bool (*)(), int, char**) (in /<path_to>/libboost_unit_test_framework-gcc34-mt-1_36.so.1.36.0) ==12285== by 0x4147F0: main (init.cpp:132) ==12285== Address 0x7FEFFF3B0 is on thread 1 stack ==12285== ==12285== ERROR SUMMARY: 6 errors from 1 contexts (suppressed: 4 from 1) ==12285== malloc/free: in use at exit: 190,112 bytes in 1,869 blocks. ==12285== malloc/free: 23,128 allocs, 21,259 frees, 2,520,845 bytes allocated. ==12285== For counts of detected errors, rerun with: -v ==12285== searching for pointers to 1,869 not-freed blocks. ==12285== checked 2,184,272 bytes. ==12285== ==12285== LEAK SUMMARY: ==12285== definitely lost: 0 bytes in 0 blocks. ==12285== possibly lost: 0 bytes in 0 blocks. ==12285== still reachable: 190,112 bytes in 1,869 blocks. ==12285== suppressed: 0 bytes in 0 blocks. ==12285== Reachable blocks (those to which a pointer was found) are not shown. ==12285== To see them, rerun with: --show-reachable=yes 

Of course, I ran this in debug mode (although, as I said, the error only occurs in release mode). If I run valgrind in release mode, I get the same result (maybe less details like the #s line). This shows that the problem is somehow in boost-1.36, or, perhaps, in my definition of init_unit_test_suite? It is clear that I can try to run using boost-1.39 on all platforms; but unfortunately, we are currently on boost-1.36 for RHEL4 and VS2005, and therefore this may not be entirely practical.

I also notice that forcing some log output to the console at the point where the test fails allows you to pass the test (not good, I know)! Suspecting that this may be due to the fact that I commented on the entire output of the log and ran the command valgrind - so that posted above. If you need code snippets of the init_unit_test_suite function; I can post this if that helps. Any ideas to solve this problem are welcome and much appreciated.

05/26/2011 Edit:

Here's init_unit_test_suite - rate it if anyone can take a look.

 std::ofstream log_stream; std::ofstream report_stream; const_string retrieve_framework_parameter( const_string cla_name, int argc, char** argv ) { //- first try to find parameter among command line arguments if present if( argc ) { //- locate corresponding cla name if( !cla_name.is_empty() ) { for( int i = 1; i < argc; ++i ) { if( cla_name == const_string( argv[i], cla_name.size() ) && argv[i][cla_name.size()] == '=' ) { const_string result = argv[i] + cla_name.size() + 1; for( int j = i; j < argc; ++j ) { argv[j] = argv[j+1]; } --argc; return result; } } } } return std::getenv( cla_name.begin() ); } //! Format results to CPP UNIT xml class simple_report_formatter : public results_reporter::format { public: virtual void results_report_start( std::ostream&) { } virtual void results_report_finish( std::ostream&) { } virtual void test_unit_report_start(test_unit const&, std::ostream&) { } virtual void test_unit_report_finish(test_unit const& tu, std::ostream& out) { if( tu.p_type == tut_case ) { const test_results& r = results_collector.results(tu.p_id); if( r.passed() ) { out<<"[PASS] "; } else { out<<"[FAIL] "; } out<<"Test Case <unit_"<<tu.p_name.get()<<"> "; if( !r.passed() ) { out<<" - "; out<<"!! Assertions failed: "<<r.p_assertions_failed; out<<" - See log files for details on failures !!"; } out<<std::endl; #if defined(MYPROJ_WINDOWS) && defined(MYPROJ_DEBUG) if( !r.passed() ) { std::ostringstream msg; msg<<"!! "<<tu.p_name.get()<<" FAILED !!"<<std::endl; OutputDebugStringA(msg.str().c_str()); } #endif } } virtual void do_confirmation_report(test_unit const&, std::ostream&) { } }; bool init_unit_test_suite() { const_string log_file = retrieve_framework_parameter( "--log_file", framework::master_test_suite().argc, framework::master_test_suite().argv ); if( !log_file.empty() ) { log_stream.open(log_file.begin()); unit_test_log.set_stream(log_stream); } const_string report_file = retrieve_framework_parameter( "--report_file", framework::master_test_suite().argc, framework::master_test_suite().argv ); if( !report_file.empty() ) { report_stream.open(report_file.begin()); results_reporter::set_stream(report_stream); } if( runtime_config::report_format() == CLF ) { results_reporter::set_format(new simple_report_formatter); } // This is providing the sensible default configuration when the test is being run // without any input parameters whatsoever: print the final report to console if( framework::master_test_suite().argc <= 1 ) { results_reporter::set_stream(std::cout); results_reporter::set_format(new simple_report_formatter); results_reporter::set_level(DETAILED_REPORT); } framework::master_test_suite().p_name.set(MYPROJ_TEST_SUITE_NAME); return true; } 
+4
source share
1 answer

This "error" in valgrind is not necessarily a problem. When a system call is invoked on Linux, memory often has to be copied from user space to kernel space. However, it can copy uninitialized bytes.

Just because it copies these bytes to the kernel space does not mean that the kernel will really do anything with uninitialized bytes. What the kernel does with bytes is highly dependent on the semantics of the system call in question.

Valgrind has no easy way to find out if it is normal that some of the bytes passed in a system call are not initialized, so it always signals an error. Many of these errors are suppressed by valgrind.

In this file you can see some valgrind default exceptions: /usr/lib/valgrind/default.supp . You can also create your own suppression files if you want, and use them in your unit test to suppress the error message. If you do not have real problems in this system, then suppressing this error is probably a good idea. See valgrind command line options.

+1
source

All Articles