Re: Rép : XCode, cin and string (C++) => troubles :s
Re: Rép : XCode, cin and string (C++) => troubles :s
- Subject: Re: Rép : XCode, cin and string (C++) => troubles :s
- From: Andreas Grosam <email@hidden>
- Date: Sun, 14 Feb 2010 20:04:02 +0100
Well, I was curious and did some more investigation.
Firstly, I was wrong that the preprocessor symbols _GLIBCXX_DEBUG, and _GLIBCXX_DEBUG_PEDANTIC can not be set in Xcode for client programs. In fact, these symbols affect only the headers included - but do not have any dependency on library code. So, these switches are not private, and according the C++ Lib documentation these are means for debugging client applications.
Consequently, the Xcode project template is correct. As a measurement for testing, I put them back.
But, if these switches are set, this strange error occurs. So, what is happening? I looked even deeper into the details, and it turned out that it became pretty weird:
Your main program looks like this:
int main (int argc, char * const argv[]) {
string input = "";
getline(cin, input);
std::cout << "input: " << input << std::endl;
return 0;
}
the error:
test(81379) malloc: *** error for object 0x1000062a0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Program received signal: “SIGABRT”.
The stack when the pointer is attempted to be freed, is as follows:
#0 0x7fff80d5bfe6 in __kill
#1 0x7fff80dfce32 in abort
#2 0x7fff80d14155 in free
#3 0x7fff86ce71e8 in std::string::reserve
#4 0x7fff86ce7243 in std::string::push_back
#5 0x7fff86cd02b5 in std::getline<char, std::char_traits<char>, std::allocator<char> >
#6 0x100002919 in std::getline<char, std::char_traits<char>, std::allocator<char> > at basic_string.h:2451
#7 0x1000013de in main at main.cpp:73
It should be noted, that the C++ library functions are almost all template functions, and many are inlined. All these functions will be "included", then instantiated, and then form a single translation unit with the main program. You can get a view how this looks like, when calling the preprocessor on main.cpp
And, it should also be noted, that Xcode is not able to debug template functions :(
As a first attempt to figure out what's happening and where, I simulated the getline function at this point where the error occurs in the original function according the stack:
int main (int argc, char * const argv[]) {
string input = "";
input += 'c';
return 0;
}
---> no error, strange because this would call push_back(), then reserve() - but here is no error.
int main (int argc, char * const argv[]) {
string input = "";
input.reserve(10);
return 0;
}
---> no error, strange - same as above.
Hm, maybe something strange is happening in getline?
Debugging was impossible, this is a template function, and gdb cannot find sources. So, I decided make a copy of the getline function, and use and debug this one. Just not as a template function, but exactly equal the function the compiler would instantiate. I gave it a different name in order to not conflict with the template function, which would always selected before a normal function. It looks as follows, which is essentially verbatim copy of the template function, but instantiated "by hand":
std::istream&
get(std::istream& __in, std::string& __str, char __delim)
{
typedef istream __istream_type;
typedef __istream_type::int_type __int_type;
typedef __istream_type::__streambuf_type __streambuf_type;
typedef __istream_type::__ctype_type __ctype_type;
typedef std::string __string_type;
typedef __string_type::size_type __size_type;
__size_type __extracted = 0;
const __size_type __n = __str.max_size();
ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
__istream_type::sentry __cerb(__in, true);
if (__cerb)
{
try
{
__str.erase();
const __int_type __idelim = std::char_traits<char>::to_int_type(__delim);
const __int_type __eof = std::char_traits<char>::eof();
__streambuf_type* __sb = __in.rdbuf();
__int_type __c = __sb->sgetc();
while (__extracted < __n
&& !std::char_traits<char>::eq_int_type(__c, __eof)
&& !std::char_traits<char>::eq_int_type(__c, __idelim))
{
__str += std::char_traits<char>::to_char_type(__c);
++__extracted;
__c = __sb->snextc();
}
if (std::char_traits<char>::eq_int_type(__c, __eof))
__err |= ios_base::eofbit;
else if (std::char_traits<char>::eq_int_type(__c, __idelim))
{
++__extracted;
__sb->sbumpc();
}
else
__err |= ios_base::failbit;
}
catch(...)
{
__in._M_setstate(ios_base::badbit);
}
}
if (!__extracted)
__err |= ios_base::failbit;
if (__err)
__in.setstate(__err);
return __in;
}
So, then I ran the supposedly identical program again:
int main (int argc, char * const argv[]) {
string input = "";
char delimiter = cin.widen('\n');
get(cin, input, delimiter);
std::cout << "input: " << input << std::endl;
return 0;
}
And?
NO error!! ??
Yes, no error. In *theory* the programs MUST not differ. So, there should be the same error - but no.
The original uses a template function, the second uses a normal function, which is identical. So, if I am right, it seems the compiler does some weird stuff when instantiating the template function.
Please note, this program does not depend on libraries, it is for the most part, headers only - especially where it fails. The real difference turns out to be the instantiation of the template function, which is a compiler thingy.
Regards
Andreas
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden