Examining C++ objects in gdb backtrace after crash - c++

I am learning debugging with GDB and I am not sure what to do.
I run a program inside GDB, that I need to get working, and it crashes with SEGFAULT. When I do backtrace inside GDB, I see this.
(gdb) backtrace
#0 0x08200100 in boost::shared_ptr<boost::re_detail::basic_regex_implementation<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > >::get (this=0x2) at /usr/include/boost/smart_ptr/shared_ptr.hpp:668
#1 0x081f94c3 in boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::get_traits (this=0x2) at /usr/include/boost/regex/v4/basic_regex.hpp:619
#2 0x081ef769 in boost::re_detail::perl_matcher<__gnu_cxx::__normal_iterator<char const*, std::string>, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<char const*, std::string> > >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::perl_matcher (this=0xb60d3eb4, first=..., end=..., what=..., e=...,
f=boost::regex_constants::match_any, l_base=...) at /usr/include/boost/regex/v4/perl_matcher.hpp:372
#3 0x081e2214 in boost::regex_match<__gnu_cxx::__normal_iterator<char const*, std::string>, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<char const*, std::string> > >, char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > (first=..., last=..., m=..., e=..., flags=boost::regex_constants::match_any)
at /usr/include/boost/regex/v4/regex_match.hpp:49
#4 0x081d43bf in boost::regex_match<std::char_traits<char>, std::allocator<char>, char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > (s=..., e=..., flags=boost::regex_constants::match_default)
at /usr/include/boost/regex/v4/regex_match.hpp:100
#5 0x081ca3c1 in [my project] (this=0x2, request=0xb5706630)
at [source of my project]:127
[more calls here]
Now I want to examine what was inside request at #5, on the line 127. Request is a C-style pointer to C++ object of class request_data, which is defined in my project. The definition of my function is bool match_request(request_data *request) const.
What should I write in gdb to actually get to the content of request as it was before the program segfaulted?

Well, your this pointer at #5 does not look too healthy, but aside from that, I think you need a GDB tutorial:
How to change stack frames
How to examine variables

This does it.
(gdb) frame 5
(gdb) print *request

Related

C++ 14 - segmentation fault fixed by calling empty method on struct?

So everything was working great until I decided to comment out a print method (for debugging). Once I commented it out, my code began to seg fault.
I assumed this was because I was somehow modifying something in my print method, so I commented out one line at a time so I could find where it was happening. After commenting every single line in the print out, I noticed it would seg fault only when I wasn't calling the print method (even if it was completely empty!).
So I did this:
void emptyMethod(Qclass c) {}
void Typechecker::initializeClasses(AST::Node *astRoot) {
...
Qclass clazz;
...
this->classes[clazz.name] = clazz;
emptyMethod(clazz); // I have no idea why I have to do this, but it
seg faults if I don't
...
}
This fixes my seg fault.
Structs in question:
struct Qclass; // forward declare
struct Qmethod {
AST::Node *node; // pointer to the node in the tree
// The reference to the containing class of a method is a pointer because
// it may not be fully initialized when passed into any given Qmethod.
// This is okay because we don't use *clazz until after all initialization is
complete.
Qclass *clazz;
std::string name;
std::vector<std::string> init;
std::map<std::string, std::string> type;
std::vector<AST::Node*> stmts;
};
struct Qclass {
AST::Node *node; // pointer to the node in the tree
std::string name;
std::string super;
Qmethod constructor;
std::vector<Qmethod> methods;
// for use in init before use checking in non constructor methods
std::vector<std::string> instanceVars;
};
Where it is seg faulting:
bool Typechecker::initCheckStmt(Qmethod &method, AST::Node *stmt, bool isConstructor) {
...
method.clazz->instanceVars.push_back(left->get(IDENT)->name); // seg faults here when not calling the empty method
...
return true;
}
Seg fault error:
#0 0x00007fffff1919b8 in std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char>
>::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > const&) () from /usr/lib/x86_64-linux-
gnu/libstdc++.so.6
#1 0x000000000041ab38 in void __gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
#2 0x0000000000417dc6 in void std::allocator_traits<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
#3 0x0000000000415b56 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
#4 0x00000000004136b3 in Typechecker::initCheckStmt(Qmethod&, AST::Node*, bool) ()
#5 0x00000000004134b9 in Typechecker::getLeaves(Qmethod&, AST::Node*, std::vector<AST::Node*, std::allocator<AST::Node*> >&, bool) ()
#6 0x00000000004137c8 in Typechecker::initCheckQmethod(Qmethod&, bool) ()
#7 0x0000000000413a16 in Typechecker::initializeBeforeUseCheck() ()
#8 0x0000000000413d12 in Typechecker::checkProgram() ()
#9 0x0000000000426e7b in main ()
I can see it must have something to do with the instanceVars vector, but I don't understand why an empty method call would fix it. My Googling ability isn't helping me at all, so any pointers would be very much appreciated.
(this code is for a compilers course)
You've got yourself some undefined behavior. Your program is doing something—maybe an out-of-bounds memory access, who knows—that is throwing off your program. In C++, when your program does that, all bets are off for what it does next, including segfaulting.
That empty method call is hiding the bug, but it's not fixing the bug. As you correctly noted, that method call shouldn't affect whether it segfaults. The reason why it does is because of the undefined behavior.
To solvev this, you'll need to look at the rest of your program to determine where there might be an issue. Just the one line where it broke isn't enough; you should look before and after the line where it ends up segfaulting, as well as what you're passing into initializeClasses.

How can I debug Boost by viewing the file after precompilation?

I'm getting a very weird bug when defining a test suite with boost like this:
BOOST_AUTO_TEST_SUITE(zerocoin_implementation_tests)
The error looks like this:
terminate called after throwing an instance of 'std::length_error'
what(): basic_string::_M_create
Here's the relevant backtrace:
#5 0x00007ffff5ce6fe8 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007ffff5ce2875 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007ffff5d7c949 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned long&, unsigned long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8 0x00007ffff70afe15 in boost::unit_test::test_unit::test_unit(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long, boost::unit_test::test_unit_type) () from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#9 0x00007ffff70b0456 in boost::unit_test::test_suite::test_suite(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long) () from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#10 0x00007ffff70b0612 in boost::unit_test::ut_detail::auto_test_unit_registrar::auto_test_unit_registrar(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long, boost::unit_test::decorator::collector&) ()
from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
From what I can tell, this has to do with Boost trying to create a max length string. I'd like to see exactly what it is doing. What's the best way of expanding boost macros to see the pre-compiled version?
Side Note
Weirdly, if I change the line very slightly to:
BOOST_AUTO_TEST_SUITE(zerocsoin_implementation_tests)
I get the following error:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
And backtrace:
#6 0x00007ffff5ce7594 in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007ffff70afe15 in boost::unit_test::test_unit::test_unit(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long, boost::unit_test::test_unit_type) () from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#8 0x00007ffff70b0456 in boost::unit_test::test_suite::test_suite(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long) () from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
#9 0x00007ffff70b0612 in boost::unit_test::ut_detail::auto_test_unit_registrar::auto_test_unit_registrar(boost::unit_test::basic_cstring<char const>, boost::unit_test::basic_cstring<char const>, unsigned long, boost::unit_test::decorator::collector&) ()
from /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.65.1
The source code for the file (and the rest of the project) can be found here: https://github.com/phoreproject/Phore/blob/segwit/src/test/zerocoin_implementation_tests.cpp
Diff that probably caused the bug: https://github.com/phoreproject/phore/compare/master...segwit#diff-bb4f094cc636d668944ed6af9b72c0d9
Two approaches:
Exception Breakpoints
Just start the test in the debugger and catch the exception.
In gdb you could do
(gdb) catch throw
Catchpoint 2 (throw)
which act like a general breakpoint. Visual Studio has a Manage Exeptions dialog.¹
Boost Test Breakpoints
For debugging Boost Test I like to set a break at the test_method member of the specific test case class I want to break at. E.g. with a test_runner that has a few nested suites like:
./test_runner --list_content
import*
utility*
xml*
xml_utilities*
child_text_test*
loggable_xml_path_test*
And we run these 3 tests like:
./test_runner -t import/utility/xml
Running 3 test cases...
*** No errors detected
To debug them with gdb I'd do
gdb ./test_runner
start -t import/utility/xml
Which stops at main, then I type:
break import::utility::xml
Auto completion helps, so to get the exact names, you can just pick from the completions:
xml
xml::as_element(xmlpp::Node const&)
xml::attr_value(xmlpp::Element const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
xml::attr_value(xmlpp::Node const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
xml::child_text[abi:cxx11](xmlpp::Element const&, char const*)
xml::child_text_test
xml::child_text_test::test_method()
xml::child_text_test_invoker()
xml::child_text_test_registrar62
xml::end_suite94_registrar94
xml::first_child(xmlpp::Element const&, char const*)
xml::get_content[abi:cxx11](xmlpp::Element const&)
xml::get_content[abi:cxx11](xmlpp::Node const*)
xml::is_attr_value(xmlpp::Node const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
xml::loggable_xml_path[abi:cxx11](xmlpp::Node const&)
xml::loggable_xml_path_test
xml::loggable_xml_path_test::test_method()
xml::loggable_xml_path_test_invoker()
xml::loggable_xml_path_test_registrar77
xml::trace_xml(xmlpp::Element const&, LogSource::LogTx)
xml::trace_xml_formatted(xmlpp::Element const&, LogSource::LogTx)
xml::xml_registrar20
xml::xml_utilities
xml::xml_utilities::test_method()
xml::xml_utilities_invoker()
xml::xml_utilities_registrar22
Pick the ones named test_method(), e.g.
break import::utility::xml::child_text_test::test_method()
Breakpoint 2 at 0x730762: file /path/src/import/utility/xml_tests.cpp, line 62.
Now you can continue execution and the debugger will automatic pause execution at the start of your unit test.
¹ see also
Make Visual Studio break on User (std::exception) Exceptions?
How do I make VC++'s debugger break on exceptions?

How can I suppress a stack-buffer-overflow from AddressSanitizer in gcc

My app is using boost::program_options and it's triggering an AddressSanitizer "stack-buffer-overflow" while generating an error message from an exception.
I'm not worried about the boost bug - the functionality works and this is just in the command line parsing portion of a non-production app. However I'd like to suppress the AddressSanitizer message.
ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffe6ce7070 at pc 0x0000007406cd bp 0x7fffe6ce6fe0 sp 0x7fffe6ce6fd8
READ of size 8 at 0x7fffe6ce7070 thread T0
#0 0x7406cc in std::_Head_base<0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, false>::_M_head(std::_Head_base<0ul, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, false>&) /frc/toolchain6/include/c++/5.3.0/tuple:142
#1 0x7406cc in _M_create_node /frc/toolchain6/include/c++/5.3.0/tuple:347
#2 0x7403fd in std::_Rb_tree_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_emplace_hint_unique<std::piecewise_construct_t const&, std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>, std::tuple<> >(std::_Rb_tree_const_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::piecewise_construct_t const&, std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&>&&, std::tuple<>&&) /frc/toolchain6/include/c++/5.3.0/bits/stl_tree.h:2170
#3 0xd5eff8 in boost::program_options::error_with_option_name::substitute_placeholders(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const (/home/joe/myapp_workspace/myapp/myapp-debug+0xd5eff8)
#4 0xd5c0dd in boost::program_options::error_with_option_name::what() const (/home/joe/myapp_workspace/myapp/myapp-debug+0xd5c0dd)
#5 0x58addf in main /home/joe/myapp_workspace/myapp/main.cpp:62
#6 0x7fd7e056176c in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2176c)
#7 0x436aa0 (/home/joe/myapp_workspace/myapp/myapp-debug+0x436aa0)
I've tried using the ASAN_OPTIONS suppression file method but that only seems to support a very short list of error types (such as "vptr_check" and "leak").
I don't think there's an easy way to suppress this error - Clang version of Asan has blacklisting mechanism but it's context insensitive so you'd have to disable memory checking in all usages of std::string which is highly undesirable.
One option is to use -fsanitize-recover=address compiler flag and add halt_on_error=0 to your ASAN_OPTIONS environment variable (see wiki for details and note that recovery is only supported is relatively new GCC and Clang). This will continue execution after first error. You'll then be able to examine full Asan report and select what interests you.

Do we need to define BOOST_SPIRIT_THREADSAFE if we are using read_json in different process

We are using read_json() in different processes and we are getting below crashes.
#0 0x00007f062ce0d094 in std::mem_fun1_t<int, boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >, boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> >*>::operator() (this=0x7f06120f4c90, __p=0x7f05f813faa0, __x=0x7f06120f4df0) at /usr/lib/gcc/x86_64-spcdn-linux-gnu/4.5.2/../../../../include/c++/4.5.2/bits/stl_function.h:605
#1 0x00007f062ce0c66e in std::binder2nd<std::mem_fun1_t<int, boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >, boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> >*> >::operator() (this=0x7f06120f4c90, __x=#0x7f06001446e0) at /usr/lib/gcc/x86_64-spcdn-linux-gnu/4.5.2/../../../../include/c++/4.5.2/backward/binders.h:154
#2 0x00007f062ce0b87e in std::for_each<std::reverse_iterator<__gnu_cxx::__normal_iterator<boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >**, std::vector<boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >*, std::allocator<boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >*> > > >, std::binder2nd<std::mem_fun1_t<int, boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >, boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> >*> > > (__first=..., __last=..., __f=...) at /usr/lib/gcc/x86_64-spcdn-linux-gnu/4.5.2/../../../../include/c++/4.5.2/bits/stl_algo.h:4185
#3 0x00007f062ce0aa88 in boost::spirit::classic::impl::grammar_destruct<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > > (self=0x7f06120f4df0) at /usr/include/boost/spirit/home/classic/core/non_terminal/impl/grammar.ipp:324
#4 0x00007f062ce09c5f in boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> >::~grammar (this=0x7f06120f4df0, __in_chrg=<optimized out>) at /usr/include/boost/spirit/home/classic/core/non_terminal/grammar.hpp:52
#5 0x00007f062ce093f7 in boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::~json_grammar (this=0x7f06120f4df0, __in_chrg=<optimized out>) at /usr/include/boost/property_tree/detail/json_parser_read.hpp:162
#6 0x00007f062ce0987f in boost::property_tree::json_parser::read_json_internal<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > > (stream=..., pt=..., filename="") at /usr/include/boost/property_tree/detail/json_parser_read.hpp:310
#7 0x00007f062ce08eb6 in boost::property_tree::json_parser::read_json<boost::property_tree::basic_ptree<std::string, std::string, std::less<std::string> > > (stream=..., pt=...) at /usr/include/boost/property_tree/json_parser.hpp:45
But when I define BOOST_SPIRIT_THREADSAFE at every place where I used this function, every thing is working fine. But I didn't understand this because every process will be having different address space. So even Sprit annoyingly makes a static variable in grammar.ipp that'll be shared amongst all instances of Spirit, how it will be shared across different processes?
So even Sprit annoyingly makes a static variable in grammar.ipp that'll be shared amongst all instances of Spirit, how it will be shared across different processes?
It isn't. Period.
Your program might share some files/named kernel objects on it's own, but the library doesn't.
This gives me worries though:
But when I define BOOST_SPIRIT_THREADSAFE at every place where I used this function
You should define it globally. That is before inclusion of ANY boost header in ALL translation units.
Failure to do so at least fails to guarantee that all global state is guarded (think of locale character classification and properties) and might easily violate the One-Definition-Rule

How to include/link boost::regex library?

I am trying to use the boost regex library but I can't manage to compile my program. All related questions which involve similar error messages seem to relate to situations where regex library wasn't properly linked. I think that I am linking it, but maybe I am doing something stupid... Perhaps someone sees my mistake?
Here is my test program:
// ~/workspace/test/test.cpp
#include <string>
#include <iostream>
#include <boost/regex.hpp>
int main(){
std::string s("abaab");
boost::regex r("[ab]*");
std::cout << boost::regex_match(s,r) << std::endl;
}
Here are the boost binaries (I installed them via synaptic on Xubuntu):
/usr/lib/i386-linux-gnu$ ls libboost_regex* -al
-rw-r--r-- 1 root root 2169582 Okt 13 05:14 libboost_regex.a
lrwxrwxrwx 1 root root 24 Okt 13 05:13 libboost_regex.so -> libboost_regex.so.1.53.0
-rw-r--r-- 1 root root 1002568 Okt 13 05:14 libboost_regex.so.1.53.0
Nevertheless I'm getting quite an ugly error message when running
~/workspace/test$ g++ -L/usr/lib/i386-linux-gnu/ -lboost_regex test.cpp
Here is the complete message:
~/workspace/test$ g++ -L/usr/lib/i386-linux-gnu/ -lboost_regex test.cpp
/tmp/cc1yDf0v.o: In function `bool boost::regex_match<__gnu_cxx::__normal_iterator<char const*, std::string>, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<char const*, std::string> > >, char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >(__gnu_cxx::__normal_iterator<char const*, std::string>, __gnu_cxx::__normal_iterator<char const*, std::string>, boost::match_results<__gnu_cxx::__normal_iterator<char const*, std::string>, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<char const*, std::string> > > >&, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags)':
test.cpp:(.text._ZN5boost11regex_matchIN9__gnu_cxx17__normal_iteratorIPKcSsEESaINS_9sub_matchIS5_EEEcNS_12regex_traitsIcNS_16cpp_regex_traitsIcEEEEEEbT_SD_RNS_13match_resultsISD_T0_EERKNS_11basic_regexIT1_T2_EENS_15regex_constants12_match_flagsE[_ZN5boost11regex_matchIN9__gnu_cxx17__normal_iteratorIPKcSsEESaINS_9sub_matchIS5_EEEcNS_12regex_traitsIcNS_16cpp_regex_traitsIcEEEEEEbT_SD_RNS_13match_resultsISD_T0_EERKNS_11basic_regexIT1_T2_EENS_15regex_constants12_match_flagsE]+0x4c): undefined reference to `boost::re_detail::perl_matcher<__gnu_cxx::__normal_iterator<char const*, std::string>, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<char const*, std::string> > >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::match()'
/tmp/cc1yDf0v.o: In function `boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::assign(char const*, char const*, unsigned int)':
test.cpp:(.text._ZN5boost11basic_regexIcNS_12regex_traitsIcNS_16cpp_regex_traitsIcEEEEE6assignEPKcS7_j[_ZN5boost11basic_regexIcNS_12regex_traitsIcNS_16cpp_regex_traitsIcEEEEE6assignEPKcS7_j]+0x22): undefined reference to `boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::do_assign(char const*, char const*, unsigned int)'
/tmp/cc1yDf0v.o: In function `boost::re_detail::perl_matcher<__gnu_cxx::__normal_iterator<char const*, std::string>, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<char const*, std::string> > >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::perl_matcher(__gnu_cxx::__normal_iterator<char const*, std::string>, __gnu_cxx::__normal_iterator<char const*, std::string>, boost::match_results<__gnu_cxx::__normal_iterator<char const*, std::string>, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<char const*, std::string> > > >&, boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags, __gnu_cxx::__normal_iterator<char const*, std::string>)':
test.cpp:(.text._ZN5boost9re_detail12perl_matcherIN9__gnu_cxx17__normal_iteratorIPKcSsEESaINS_9sub_matchIS6_EEENS_12regex_traitsIcNS_16cpp_regex_traitsIcEEEEEC2ES6_S6_RNS_13match_resultsIS6_S9_EERKNS_11basic_regexIcSD_EENS_15regex_constants12_match_flagsES6_[_ZN5boost9re_detail12perl_matcherIN9__gnu_cxx17__normal_iteratorIPKcSsEESaINS_9sub_matchIS6_EEENS_12regex_traitsIcNS_16cpp_regex_traitsIcEEEEEC5ES6_S6_RNS_13match_resultsIS6_S9_EERKNS_11basic_regexIcSD_EENS_15regex_constants12_match_flagsES6_]+0xcd): undefined reference to `boost::re_detail::perl_matcher<__gnu_cxx::__normal_iterator<char const*, std::string>, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<char const*, std::string> > >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::construct_init(boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > > const&, boost::regex_constants::_match_flags)'
collect2: error: ld returned 1 exit status
The header seems to be found, right? How else could gcc know about boost::re_detail::perl_matcher or boost::basic_regex?
I have no clue what the problem might be. Maybe it is the linking after all?
Thanks in advance!
You just needed to make sure the library comes after your own sources.
g++ -L/usr/lib/i386-linux-gnu/ test.cpp -lboost_regex
This is a FAQ:
Why does the order in which libraries are linked sometimes cause errors in GCC?
g++ linking order dependency when linking c code to c++ code
And probably quite a few more. I guess it's (sadly) one of those rites-of-passage that goes with the territory :(