Reputation: 2614
I'm trying to compile and run this harmless looking class in g++ but the program keeps segfaulting either on malloc or memmove. There is hardly anything going on here.
I receive the following error when compiling with -g and running it through gdb. This is the extent of what I know on how to debug this.
For some reason this only segfaults when compiled from two separate files. If I copy/paste everything into main.cpp it runs fine.
Windows/Cygwin g++ (GCC) 4.9.2:
Program received signal SIGSEGV, Segmentation fault.
0x61137eb5 in memmove () from /usr/bin/cygwin1.dll
..
Program received signal SIGSEGV, Segmentation fault.
0x610ef417 in muto::acquire(unsigned long) () from /usr/bin/cygwin1.dll
Windows/g++ 4.9.2-TDM:
Program received signal SIGSEGV, Segmentation fault.
0x777d27d0 in ntdll!RtlCompareMemoryUlong () from /c/Windows/SysWOW64/ntdll.dll
Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7279ef5 in _int_malloc () from /lib64/libc.so.6 Missing separate debuginfos, use: debuginfo-install glibc-2.17-55.el7_0.5.x86_64 libgcc-4.8.2-16.2.el7_0.x86_64 libstdc++-4.8.2-16.2.el7_0.x86_64 ..
CentOS 7/g++ (GCC) 4.8.2:
Program received signal SIGSEGV, Segmentation fault.
_int_malloc (av=0x7ffff75b6760 , bytes=29) at malloc.c:3281
3281 {
I'm compiling using the following flags:
-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Wno-unused
What am I missing? Is there anything else I can do in gdb to help pinpoint the problem?
$ g++ main.cpp string_t.cpp -g -std=c++11 $DEBUG -o test.exe && ./test.exe
main.cpp
#include <iostream>
using std::cout;
using std::endl;
#include "string_t.h"
int main() {
string_t a("test");
cout << a << endl;
return 0;
}
string_t.h
#include <cstdint>
#include <string>
class string_t {
std::basic_string<char> _base;
public:
string_t(
const char* s);
friend std::ostream& operator<<(
std::ostream& l,
const string_t& r);
};
string_t.cpp
#include "string_t.h"
string_t::string_t(
const char* s) :
_base(s) {
}
std::ostream& operator<<(
std::ostream& l,
const string_t& r)
{
l << r._base.c_str();
return l;
}
Upvotes: 2
Views: 3277
Reputation: 1678
You did not include <ostream>
into the second translation unit (string_t.cpp), so overload resolution fails to find
template<class CharT, class Traits>
basic_ostream<CharT,Traits>& operator << (basic_ostream<CharT,Traits>& os, const char* s);
when you invoke
l << r._base.c_str();
Instead, string_t(const char* s)
is used as a conversion constructor (it is not declared explicit
) to create a new string_t object and
std::ostream& operator<<(std::ostream& l, const string_t& r)
is called again, so you end up with infinite recursion.
Upvotes: 3