使用boost 1.36和C ++发布RHEL4版本(Issue on RHEL4 release using boost 1.36 and C++)

编程入门 行业动态 更新时间:2024-10-25 22:35:59
使用boost 1.36和C ++发布RHEL4版本(Issue on RHEL4 release using boost 1.36 and C++)

我正在努力解决一个我在RHEL4版本上看到的神秘问题。 我的一些单元测试(使用boost 1.36单元测试框架)在RHEL4(gcc 3.4.6)上失败并且使用发布构建类型。 我没有看到使用RHEL5版本或调试版本类型(gcc 4.1.2,boost-1.39)的问题; 我也不使用Visual Studio 2005(使用boost-1.36)或2008(使用boost-1.39)在Windows 32位或64位上看到它。

怀疑这可能是由于一些微妙的内存问题,我继续在测试应用程序上运行valgrind(保留问题的最小案例)。 这是我在使用“完全不可达”模式运行valgrind时得到的结果:

==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's 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

当然,我以调试模式运行它(尽管正如我所提到的,错误只发生在发布模式中)。 如果我在释放模式下运行valgrind,我会得到相同的输出(可能不太详细,如行号)。 从这看来,这个问题似乎在boost-1.36,或者我的init_unit_test_suite的定义? 显然,我可以尝试的一件事是在所有平台上使用boost-1.39; 但不幸的是,我们目前在RHEL4和VS2005上使用boost-1.36,所以这可能不实用。

我还观察到,在测试失败的地方强制某个记录器输出到控制台,使测试通过(我知道不好)! 怀疑这可能是因为我评论了所有记录器输出并运行valgrind - 所以这就是上面的内容。 如果你需要一些init_unit_test_suite函数的代码片段; 如果有帮助,我可以发布。 任何想法来解决这个问题都是受欢迎的并且非常感谢

05/26/2011编辑:

这里是init_unit_test_suite - 如果有人可以看一下,很感激。

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; }

I am struggling with a mysterious problem I only see on my RHEL4 release build. Some of my unit tests (using boost 1.36 unit test framework) fail on RHEL4 (gcc 3.4.6) and using release build-type. I do not see the problem using RHEL5 release or debug build types (gcc 4.1.2, boost-1.39); neither do I see it on Windows 32 bit or 64 bit using either Visual Studio 2005 (using boost-1.36) or 2008 (using boost-1.39).

Suspecting that this may be due to some subtle memory issue, I proceeded to run valgrind on the test application (minimal case that preserved the problem). Here is what I got when I ran valgrind using "full, no-reachable" 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's 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

Ofcourse, I ran this in debug mode (although as I mentioned the error occurs only in release mode). If I run valgrind in release mode, I get the same output (with perhaps less detail such as line #s). From this it appears that the problem is somehow in boost-1.36, or perhaps my definition of init_unit_test_suite? Clearly one thing I can try is to run using boost-1.39 on all platforms; but unfortunately, we're currently on boost-1.36 for RHEL4 and VS2005, and so this may not be practical yet.

I also observe that forcing a certain logger output to console at a point where the test fails, enables the test to pass (not good, I know)! Suspecting that this might be due that I commented all logger output and ran valgrind - so that's what's posted above. If you need some code snippets of the init_unit_test_suite function; I can post that, if it helps. Any ideas to resolve this are welcome and greatly appreciated.

05/26/2011 Edit:

Here's the init_unit_test_suite - appreciate if somebody could 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; }

最满意答案

valgrind中的这个“错误”不一定是个问题。 当在Linux中调用系统调用时,内存通常必须从用户空间复制到内核空间。 在这样做时,它可能会复制未初始化的字节。

仅仅因为它将这些字节复制到内核空间并不意味着内核实际上会对未初始化的字节做任何事情。 内核对字节的处理在很大程度上取决于所讨论的系统调用的语义。

Valgrind没有简单的方法知道在系统调用中传递的一些字节是否是未初始化的,因此它总是表示错误。 许多类似的错误被valgrind压制。

你可以在这个文件中看到一些valgrind的默认抑制: /usr/lib/valgrind/default.supp你也可以创建你自己的抑制文件,如果你喜欢,并在你的单元测试中使用它们来抑制错误信息。 如果您在此系统上没有遇到任何实际问题,那么抑制错误可能是一个好主意。 请参阅valgrind的命令行选项。

This "error" in valgrind is not necessarily a problem. When a system call is called in Linux the memory often has to be copied from users space to kernel space. In doing so the it may copy uninitialized bytes.

Just because it copies these bytes into kernel space does not mean the kernel will actually do anything with the uninitialized bytes. What the kernel does with the bytes depends heavily on the semantics of the system call in question.

Valgrind has no simple way of knowing if it is OK that some of the bytes passed in the system call are uninitialized so it always signals an error. Many of similar errors are suppressed by valgrind.

You can see some of valgrind's default suppressions in this file: /usr/lib/valgrind/default.supp You can also create your own suppression files if you like and use them in your unit test to suppress the error message. If you are not experiencing any actual problems on this system them suppressing the error is probably a good idea. See valgrind's command line options.

更多推荐

本文发布于:2023-08-04 23:36:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1423081.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:版本   boost   release   Issue

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!