STL string screwing up code...

Started by
5 comments, last by EdR 18 years, 6 months ago
This is most odd, because it doesn't occur on all machines I try it on--at least not in this particular way. The GDB output is below:

Program received signal SIGSEGV, Segmentation fault.
0x0024dc4e in _int_malloc () from /lib/libc.so.6
(gdb) where
#0  0x0024dc4e in _int_malloc () from /lib/libc.so.6
#1  0x0024f492 in malloc () from /lib/libc.so.6
#2  0x001b6bf6 in operator new () from /usr/lib/libstdc++.so.6
#3  0x00143e80 in __gnu_cxx::__pool<true>::_M_reclaim_block ()
   from /usr/lib/libstdc++.so.6
#4  0x0018e27d in std::string::_Rep::_S_create () from /usr/lib/libstdc++.so.6
#5  0x001901c1 in std::string::_M_mutate () from /usr/lib/libstdc++.so.6
#6  0x001903f0 in std::string::_M_replace_safe () from /usr/lib/libstdc++.so.6
#7  0x0019267e in std::string::replace () from /usr/lib/libstdc++.so.6
#8  0x00192c9d in std::string::replace () from /usr/lib/libstdc++.so.6
#9  0x0808cc63 in find_and_replace (source=@0xbfeeed30, find=@0xbfeeeb6c,
    replace=@0xbfeeeb64) at utils.cpp:170
#10 0x080803db in Socket::Colorize (this=0x99bd510, txt=@0xbfeeed30)
    at socket.cpp:210
#11 0x08082706 in Socket::Write (this=0x99bd510, txt=@0xbfeeed60)
    at socket.cpp:159
#12 0x0808c7c2 in send_to_char (ch=0x99bb520, text=@0xbfeeedfc) at utils.cpp:21
#13 0x0805b855 in do_who (ch=0x99bb520, arg=@0xbfeeee84, special_command=0)
    at actions_informative.cpp:111
#14 0x08061025 in command_interpreter (ch=0x99bb520, text=@0xbfeef39c)
    at commandinterpreter.cpp:118
#15 0x08085ceb in socket_state_handler (pSocket=0x99bd510)
    at statehandler.cpp:53
---Type <return> to continue, or q <return> to quit---
#16 0x08076449 in main (argc=2, argv=0xbfeef884) at main.cpp:99
I'm sure that it's obvious enough, but I bolded where my code ends and the <string> code begins. find_and_replace is a wrapper for the std::string replace function (I was far, far too lazy to be good and use the proper code for the std::string class more than once, and this was easier). Socket::Colorize is (in a hideously ugly way, let's not kid ourselves here) a battery of find_and_replace statements that replaces my defined color codes with the telnet ANSI color sequences (so that "{B" is translated into the ANSI code for bold blue--this is a MUD codebase). Socket::Write puts whatever string is passed to it into an output buffer for flushing later. do_who is where the string is compiled. It looks something like the following (though with ANSI sequences that I didn't show).

[PK?][ LVL]| Name
======================================================================
[NPK][IMPL]| Lared is sometimes AFK.
[ PK][   1]| Testbob is a newbie.
Here's the sticking point. With one lone connection it works fine (and I test against null to make sure that a player actually exists within my player stack; that isn't the issue). When a second player connects and tries to use the WHO command, it explodes. I've fought with it for the past two days and am getting no progress. Does this situation sound similar to anyone else's? Source code for the application will be available when I get home.
http://edropple.com
Advertisement
I'm not sure how you're handling multiple connections with your code. If it's multithreaded, is it possible that you're having concurrency problems accessing variables? This could cause it to look like there was a problem with the STL strings. That's the only thing I can think of off the top of my head, unless your wrapper function is buggy.
It's a single-threaded application, but in any case that wouldn't do it. The strings that are being run through the find_and_replaces are private strings limited only to the Socket class that handles connection and I/O. Nobody else could touch them anyway.

Below are the code snippets that are causing hell. The lines the GDB output above flagged are bold. ANSI_NORMAL is a macro #define of the ANSI escape sequence to revert to standard coloring. I know it works; I use it in four other projects.

void find_and_replace( std::string& source, const std::string& find, const std::string& replace ) {	size_t j;	for (;(j = source.find( find )) != std::string::npos;) {		source.replace( j, find.length(), replace );	}}std::string Socket::Colorize (std::string txt) {	find_and_replace(txt, "{{", "&&!@#*@*@*@*@*");	find_and_replace(txt, "{n", ANSI_NORMAL);	/* ... */	return txt;}void Socket::Write(std::string txt) {  outBuffer += Colorize(txt);}void send_to_char(struct char_data* ch, std::string text) {	if (ch == NULL || ch->socket == NULL || ch->purge_next_tick == TRUE)			return;	ch->socket->Write(text);}CMD(do_who) {	std::string buf;		buf = "{C[{RPK?{C][{w LVL{C]{W| {CN{came\r\n" +"{W======================================================================\r\n";		for (unsigned int i = 0; i < player_stack.size(); i++) {				if (player_stack != NULL) {						if (player_stack->flag.PK == TRUE)				buf += "{C[{R PK{C][";			else				buf += "{C[{BNPK{C][";			if (player_stack->experience.level == 101)				buf += "{W TRL";			else if (player_stack->experience.level == 102)				buf += "{WJNR1";			else if (player_stack->experience.level == 103)				buf += "{WJNR2";			else if (player_stack->experience.level == 104)				buf += "{WIMM1";			else if (player_stack->experience.level == 105)				buf += "{WIMM2";			else if (player_stack->experience.level == 106)				buf += "{WIMM3";			else if (player_stack->experience.level == 107)				buf += "{WIMM4";			else if (player_stack->experience.level == 108)				buf += "{W SNR";			else if (player_stack->experience.level == 109)				buf += "{WSNR+";			else if (player_stack->experience.level == 110)				buf += "{WIMPL";			if (player_stack->experience.level > 0 &&				player_stack->experience.level < 10)				buf += "{w   ";			if (player_stack->experience.level > 9 &&				player_stack->experience.level < 100)				buf += "{w  ";			if (player_stack->experience.level == 100)				buf += "{w ";			if (player_stack->experience.level < 101)				buf += itos(player_stack->experience.level);			buf += "{C]{W| {n";			if (player_stack->whois.pretitle != "") {				buf += player_stack->whois.pretitle;				buf += " ";			}						buf += player_stack->name;			buf += " ";						buf += player_stack->whois.title;			buf += " ";					if (!player_stack->socket) {				buf += "{R(LD)";			} else {				if (player_stack->socket->getState() == STATE_OLC) {					buf += "{G(B)";				}				if (player_stack->socket->getState() == STATE_WRITING) {					buf += "{M(W)";				}				if (player_stack->socket->getState() == STATE_DETAILING) {					buf += "{B(D)";				}			}						buf += "{n\r\n";		}	}	buf += "\r\n";	buf += itos(player_stack.size());	buf += " players displayed.\r\n";	send_to_char(ch, buf);}


What's driving me absolutely crazy is that this code has not changed at all, and it's suddenly giving me these errors.

Any help would be greatly appreciated.

Ed
http://edropple.com
I hate bumping my own posts, but has anyone run into a similar problem before?

Full source code is available if needed.
http://edropple.com
Your heap is screwed up; the crash is merely the side effect of this. The find_and_replace is performing a malloc, and the malloc is the thing crashing, when it comes across the corrupted area of the heap. Most likely, this is caused by overrunning an array somewhere earlier in your program.
Quote:Original post by Edward Ropple
Does this situation sound similar to anyone else's?


Yes, very. In all cases it has been a memory access problem somewhere earlier in the program. If you happen to be on Linux then Valgrind can point it out to you.
As a matter of fact, I am on Linux.

I'll check Valgrind out. Thanks a lot.
http://edropple.com

This topic is closed to new replies.

Advertisement