08 May, 2007, Pedlar wrote in the 1st comment:
Votes: 0
ok, so im having some problems here :(

void page_to_char (const char *txt, CHAR_DATA * ch)
{
char buffer[MAX_STRING_LENGTH * 4];
char *pbuff;

#if defined(macintosh)

send_to_char (txt, ch);
#else

if(!IS_NULLSTR(txt) && ch->desc)
{
pbuff = buffer;
colourconv (pbuff, txt, ch);
[color=red]ARRAY_NEW(ch->desc->showstr_head, char, (strlen(buffer) + 1));[/color]
strcpy (ch->desc->showstr_head, buffer);
ch->desc->showstr_point = ch->desc->showstr_head;
show_string (ch->desc, "");
}
#endif
return;
}


The red line is the one erroring out, I used macros for ease of me knowing where i was at during the whole conversion, i have totally wiped out any allocs in the MUD, and replaced em with these macros:
#define NEW(result, type, number)		(result) = new (type);

#define DELETE(point) \
do \
{ \
delete point; \
point = NULL; \
} while(0)

#define ARRAY_NEW(result, type, number) (result) = new (type)[number];

#define ARRAY_DELETE(point) \
do \
{ \
delete[] point; \
point = NULL; \
} while(0)


Quote
*** glibc detected *** malloc(): memory corruption: 0x0864dfb0 ***


is the error, im not sure why its doing it :(
08 May, 2007, kiasyn wrote in the 2nd comment:
Votes: 0
maybe something to do with strcpy? =S
09 May, 2007, Omega wrote in the 3rd comment:
Votes: 0
ch->desc->showstr_head

make sure that is not already created before you create ontop of it again.

/* Send a page to one char. */
void page_send( const char *txt, character_data * ch )
{
descriptor_data *d;

if( !ch )
{
sstm_log(LOG_BUG, "page_send: Null Character!" );
return;
}

if( NullString(txt) || ( d = ch->desc ) == NULL )
return;
if( ch->lines == 0 )
{
send_ch( txt, ch );
return;
}
/*
* If there is already some data being "paged" for this descriptor,
* append the new string.
*/
if( !NullString( d->showstr_head ) )
{
char *fub;
int i;
int size_new = strlen( txt ) + strlen( d->showstr_head ) + 2;
fub = new char[size_new];
fub[0] = '\0';
mudstrlcat( fub, d->showstr_head, size_new );
i = strlen( fub ) - strlen( d->showstr_point );
mudstrlcat( fub, txt, size_new );

ReplaceString( d->showstr_head, fub );
d->showstr_point = d->showstr_head + i;
CleanData(fub);
return;
}

ReplaceString( d->showstr_head, txt );
d->showstr_point = d->showstr_head;
page_string( d, "" );
return;
}


#define ReplaceString( p_str, n_str ) \
do \
{ \
if(!NullString(p_str)) \
{\
CleanData(p_str); \
} \
p_str = StrDup( (n_str) ); \
} while(0)


// Crazy Enhanced System!  Makes life alittle simpler one would think.
// Always makes (point) = NULL.
// Darien 27/Aug/2006 0:44
#define CleanData(point) \
do \
{ \
if(point) \
{ \
if(typeid(point) == typeid(char *) || typeid(point) == typeid(const char *)) \
{ \
delete [] point; \
} \
else \
{ \
delete (point);\
} \
(point) = NULL; \
}\
else \
{ \
mud_debug(DEBUG_MEMORY,"CleanData: Trying to clean null Data from file %s: function: %s: lines: %d", __FILE__, __PRETTY_FUNCTION__, __LINE__); \
(point) = NULL; \
} \
} while(0)


// samson helped here :P  only a little :P I swear :P
char *StrDup( const char *str )
{
static char *ret;

if(NullString(str))
{
mud_debug(DEBUG_MEMORY, "StrDup: Called with Null STR");
return NULL;
}

ret = new char[strlen(str)+1];
mudstrlcpy(ret, str, strlen(str)+1);

return ret;
}


and there you have it, straight from my mud, figure that should fix your problem, you may have to changilate it up alittle bit to fit, but do enjoy.
09 Nov, 2008, Runter wrote in the 4th comment:
Votes: 0
Old post so probably not relevant any more, but…

The error has to do with malloc() and none of the code you posted had malloc() or free() involved.

So I'm not sure if the error even had to directly do with that code. Maybe mixing malloc() and new with free() and delete.

You'd be best off using valgrind or some memory debugging tool and just finding out exactly what the memory corruption was, when it happened, and what the original allocation and scope of allocation was.
09 Nov, 2008, Sharmair wrote in the 5th comment:
Votes: 0
Actually, most likely new uses malloc() and delete uses free() internally.

As far as the error here, maybe there is a debug heap in use that is tracking memory leaks
and this is a new allocation overwriting an already allocated pointer.
09 Nov, 2008, Runter wrote in the 6th comment:
Votes: 0
Sharmair said:
Actually, most likely new uses malloc() and delete uses free() internally.

As far as the error here, maybe there is a debug heap in use that is tracking memory leaks
and this is a new allocation overwriting an already allocated pointer.


I suppose that's possible. It would depend on the implementation which isn't guaranteed to be malloc. That would be compiler specific.
I'm fairly sure the actual allocation using new makes no call to malloc, though. (Even if it does the same thing.)
09 Nov, 2008, Sharmair wrote in the 7th comment:
Votes: 0
True, it is compiler specific. My "most likely" was derived from the fact that ALL the compilers
I have looked at asm output from have in fact called the same code as malloc()/free(), I am not
saying all compilers do this, but all I have checked do. And to quote from Bruce Eckel's Thinking in C++
after introducing new "…the equivalent of malloc(sizeof(foo)) is called (often, it is literally a call to malloc())…".
09 Nov, 2008, Runter wrote in the 8th comment:
Votes: 0
Here's the thing. They don't call malloc even if its the same code.

This means they wouldn't produce a malloc memory corruption error. It's never called, the code probably is almost the same, but they don't actually make that function call. If anything it would say new there.


edit: I don't know. From the research I've done on the subject I can't guarentee that malloc itself isn't called, but I can almost guarentee that in practice throwing another function call on top is less efficient. That tends to make me believe that if the compiler is worth its salt it won't just be an actual malloc wrapper.
09 Nov, 2008, Grimble wrote in the 9th comment:
Votes: 0
As an alternative to valgrind, may I suggest…

http://memwatch.sourceforge.net/

It's easy to integrate into C software. When hunting leaks, you enable it before executing the code path you suspect causes a leak, execute the code path, then disable it and dump the statistics. It'll show you down to the file and line where memory was allocated and not released.

You may want to get into the habit of always having memwatch enabled, and dumping the statistics when the software exits (e.g., on a mud reboot). If your software is good about cleaning up all its allocated resources before exiting, you'll spot leaks fairly quickly.
09 Nov, 2008, quixadhal wrote in the 10th comment:
Votes: 0
malloc() simply reserves a fixed size chunk of space from the program heap space, marking it as in-use, and returning a pointer to the start of it. Various replacement mallocs do the same thing malloc does, namely use brk() to move the heap pointer and then mange lists (or trees) of free blocks. "new" could do that, or it could let malloc do it. GNU g++ and gcc both use the same underlying code, so it would be easier to maintain "new" that simply called malloc().

Of interest, from the malloc() man page:

Recent versions of Linux libc (later than 5.4.23) and GNU libc (2.x) include a malloc implementation which is tunable via
environment variables. When MALLOC_CHECK_ is set, a special (less efficient) implementation is used which is designed to be
tolerant against simple errors, such as double calls of free() with the same argument, or overruns of a single byte (off-by-
one bugs). Not all such errors can be protected against, however, and memory leaks can result. If MALLOC_CHECK_ is set to 0,
any detected heap corruption is silently ignored; if set to 1, a diagnostic is printed on stderr; if set to 2, abort() is
called immediately. This can be useful because otherwise a crash may happen much later, and the true cause for the problem is
then very hard to track down.
09 Nov, 2008, David Haley wrote in the 11th comment:
Votes: 0
It's not inefficient to wrap malloc is the wrapping is all done inline. Recall that new needs a chunk of memory to do its work on, which is exactly what malloc gives it. Why do you think it is necessarily so terrible for new to wrap malloc?
09 Nov, 2008, Runter wrote in the 12th comment:
Votes: 0
Because in my research some of the compiler documentation and implementation information surrounding new suggested that was their reason for potentially not wrapping malloc inside of new. (Nobody wants to actually definitively say what their underlying implementation is.)

Although, It's really a non-issue to me. It works the same and the entire point is you shouldn't have to know what the underlying implementation is.
10 Nov, 2008, Sharmair wrote in the 13th comment:
Votes: 0
Ok, just as an example of what I meant by calling the same code I did a check on the compiler I use
to develop on my computer here. The test program:
#include <malloc.h>
int main(){
int* pint = new int;
delete pint;
pint = (int*)malloc(sizeof(int));
free(pint);
return 0;
}

The asm of this so you can follow:
; 2    : int main(){
; 3 : int* pint = new int;

push 4
call ??2@YAPAXI@Z ; operator new
add esp, 4

; 4 : delete pint;

push eax
call ??3@YAXPAX@Z ; operator delete
add esp, 4

; 5 : pint = (int*)malloc(sizeof(int));

push 4
call _malloc
add esp, 4

; 6 : free(pint);

push eax
call _free
add esp, 4
xor eax, eax

; 7 : return 0;
; 8 : }

ret 0

Now, the disassembly of the actual program in memory:
00401004   push      00000004
00401006 call 004010e0 ; operator new
0040100b add esp,00000004
0040100e push eax
0040100f call 004010d0 ; operator delete
00401014 add esp,00000004
00401017 push 00000004
00401019 call 00401050 ; malloc()
0040101e add esp,00000004
00401021 push eax
00401022 call 00401030 ; free()
00401027 add esp,00000004
0040102a xor eax,eax
0040102c pop edi
0040102d pop esi
0040102e pop ebx
0040102f ret

Now, using the addresses for the function calls we can see that delete in fact does call free().
Here is operator delete, as you can see, it is just a wrapper for free (00401030):
004010d0   mov       eax,dword ptr [esp+04] ; the size arg
004010d4 push eax
004010d5 call 00401030 ; free()
004010da add esp,00000004
004010dd ret

Now, looking at operator new:
004010e0   mov       eax,dword ptr [esp+04]
004010e4 push 00000001
004010e6 push eax
004010e7 call 00401070 ; _nh_malloc()
004010ec add esp,00000008
004010ef ret

and malloc():
00401050   mov       eax,dword ptr [00404048] ; _newmode
00401055 mov ecx,dword ptr [esp+04]
00401059 push eax
0040105a push ecx
0040105b call 00401070 ; _nh_malloc()
00401060 add esp,00000008
00401063 ret

You can see they are both wrappers to the internal _nh_malloc(), with the only difference that new
calls with the new_handler flag as true, and malloc() using the _newmode setting.

If there was an error called in new (or malloc()), it would be in _nh_malloc() or an internal function
called directly or indirectly from it. So the error message would be the same.

This is just one example, and the point was made that really, why would you have a new set of code
to do the same thing as you already had code for? Other compilers might do things different, and it
should be noted that new/delete can be changed by the programmer to work any way they like, and
I am only talking of the memory allocation portion of new/delete (they do other things too).

All this is about as low level as you can get, and really, you should not have to worry about these kinds
of details, but this would explain why a line with new might give a low level error referring to malloc()
(maybe knowledge of the low level workings can be helpful in some cases).
10 Nov, 2008, Runter wrote in the 14th comment:
Votes: 0
I guess I'll say it again too. It's implementation details that are not guaranteed from compiler to compiler or even version of a certain compiler to compiler. The only thing that important about the implementation is the fact that you can't guarantee from implementation to implementation that it is using free or malloc as a wrapper.
10 Nov, 2008, David Haley wrote in the 15th comment:
Votes: 0
I'm not really sure that everybody is talking about the same thing here anymore.
0.0/15