This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Bug in STL basic_string template (2.95.2 & 2.95.3)


I just finished tracking down a bug in an application I've been
developing under Linux, and found that the cause comes from the
basic_string template in the C++ STL package included with
versions 2.95.2 and 2.95.3 of your gcc-g++ package.

My application uses std::string's HEAVILY.  I haven't gone so far
yet as to audit this, but it in fact potentially cycles through
millions of string object per hour.  This problem only pops up
after a couple days of extremely heavy load on multi-processor
systems. I've been testing it under Redhat Linux 6.2 and Mandrake
Linux 7.2/8.0 on dual-CPU systems with SMP using 2.2 and 2.4
Linux kernels on 32-bit Intel systems.  I can't speak for other
architectures ; it may only be caused by some of the assembly
optimizations I see are being used on this platform.  (note the
compiler/libraries were being built with the default settings
for "../configure --enable-threads --enable-language=c++" (the
same problem seems to have existed in the distributed RPMS for
Mandrake and Redhat)

What appears to be happening is somewhere along the way is the ref
member for the static basic_string::nilRep structure appears to
be getting decremented to zero (and in fact wrapping around
sometimes to 2^32-1).  I gather that it's a design assumption that
this reference should never get decremented beyond a value of 1
because the basic_string::Rep::release() function calls
"delete this" if it is (and from skimming through the code I can't
see a scenerio where it would).  Since the nilRep object is static,
deleting it yields unhappy results -- from this particular
experience seg faults and some serious memory problems that were
real nasty to track down.

I was able to identify this problem by adding a
basic_string::isNilRep() function:

static bool isNilRep(const Rep *p) { return p==nilRep; }

... and a check to the basic_string::Rep::release() function
whenever it went to "delete this":

if (__val == 1) {
	if (basic_string::isNilRep(this)) {
		printf("tried deleting nilRep!\n");
	} else {
		delete this;
	}
}

Patching the 2.95.2 (under Mandrake 7.2) and 2.95.3
(under Mandrake 8.0) source for this, rebuilding and installing the
compiler/libraries, and re-compiling my application yielded in:

a) it running without crashing
b) the "tried deleting nilRep!" message being printed out multiple times

Unfortunately, I can't speculate as to why this is happening but
I'm sure you guys have some ideas.  It seems that this bug is
uniquely tailored to my multi-processor i686 scenerio with heavy
loads and heavy use of std::string, so perhaps it's something with
the release() assembly (I'm not learned in assembly).  Also, I can't
offer you a test case since this was only exhibiting itself in
commercial code.  But hopefully my description will be of some help.

Anyway.. thanks for the great tools and let me know if I can be of
any help.

Regards,

Michael Dickey <miked@io.com> (long-time GNU fan)



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]