[me@localhost coolmud]$ grep 'CODE_INIT_SIZE' src/cool.h
#define CODE_INIT_SIZE 32
[me@localhost coolmud]$ gcc -v 2>&1 | grep version
gcc version 4.6.3 20120306 (Red Hat 4.6.3-2) (GCC)
[me@localhost coolmud]$ make
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/ndbm/hash.c -osrc/ndbm/hash.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/ndbm/hash_bigkey.c -osrc/ndbm/hash_bigkey.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/ndbm/hash_buf.c -osrc/ndbm/hash_buf.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/ndbm/hash_func.c -osrc/ndbm/hash_func.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/ndbm/hash_log2.c -osrc/ndbm/hash_log2.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/ndbm/hash_page.c -osrc/ndbm/hash_page.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/ndbm/ndbm.c -osrc/ndbm/ndbm.o
ar rsc src/ndbm/libndbm.a src/ndbm/hash.o src/ndbm/hash_bigkey.o src/ndbm/hash_buf.o src/ndbm/hash_func.o src/ndbm/hash_log2.o src/ndbm/hash_page.o src/ndbm/ndbm.o
byacc -l -d src/cool.y
byacc: 2 shift/reduce conflicts.
mv y.tab.c src/cool.c
mv y.tab.h src/y.tab.h
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/cool.c -osrc/cool.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/perms.c -osrc/perms.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/error.c -osrc/error.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/code.c -osrc/code.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/symbol.c -osrc/symbol.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/utils.c -osrc/utils.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/decode.c -osrc/decode.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/list.c -osrc/list.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/map.c -osrc/map.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/var.c -osrc/var.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/verb.c -osrc/verb.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/method.c -osrc/method.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/compile.c -osrc/compile.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/execute.c -osrc/execute.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/opcode.c -osrc/opcode.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/opcodes1.c -osrc/opcodes1.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/opcodes2.c -osrc/opcodes2.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/opcodes3.c -osrc/opcodes3.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/builtins.c -osrc/builtins.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/servers.c -osrc/servers.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/dispatch.c -osrc/dispatch.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/message.c -osrc/message.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/storage.c -osrc/storage.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/dbsize.c -osrc/dbsize.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/dbpack.c -osrc/dbpack.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/dbunpack.c -osrc/dbunpack.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/hash.c -osrc/hash.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/string.c -osrc/string.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/buf.c -osrc/buf.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/netio.c -osrc/netio.o
src/netio.c: In function server_input:
src/netio.c:311:5: warning: pointer targets in passing argument 6 of recvfrom differ in signedness [-Wpointer-sign]
/usr/include/sys/socket.h:166:16: note: expected socklen_t * __restrict__ but argument is of type int *
src/netio.c: In function new_player:
src/netio.c:327:40: warning: pointer targets in passing argument 3 of accept differ in signedness [-Wpointer-sign]
/usr/include/sys/socket.h:214:12: note: expected socklen_t * __restrict__ but argument is of type int *
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/playerio.c -osrc/playerio.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/serverio.c -osrc/serverio.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/cache.c -osrc/cache.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/dbmchunk.c -osrc/dbmchunk.o
gcc -c -O2 -fno-strict-aliasing -Wall -Wextra -Wno-parentheses -Wno-unused -g -Isrc/ndbm src/os.c -osrc/os.o
gcc -O2 -fno-strict-aliasing -g -obin/cm.exe src/ndbm/libndbm.a src/cool.o src/perms.o src/error.o src/code.o src/symbol.o src/utils.o src/decode.o src/list.o src/map.o src/var.o src/verb.o src/method.o src/compile.o src/execute.o src/opcode.o src/opcodes1.o src/opcodes2.o src/opcodes3.o src/builtins.o src/servers.o src/dispatch.o src/message.o src/storage.o src/dbsize.o src/dbpack.o src/dbunpack.o src/hash.o src/string.o src/buf.o src/netio.o src/playerio.o src/serverio.o src/cache.o src/dbmchunk.o src/os.o -Lsrc/ndbm -lcrypt -lndbm
rm -f west.tmp
for file in bin/root_obj.cl bin/sys_obj.cl bin/located_obj.cl bin/described_obj.cl bin/thing.cl bin/container.cl bin/room.cl bin/exit.cl bin/player.cl bin/builder.cl bin/programmer.cl bin/wizard.cl bin/west.cl; do gcc -E -P -x c $file >> west.tmp; done
bin/cm.exe bin/west -i -f west.tmp
May 22 22:07:51: Reading config file from bin/west.cfg
May 22 22:07:51: Cache depth starts at 23 slots.
May 22 22:07:51: Cache width is 7 slots.
May 22 22:07:51: Initializing db
May 22 22:07:51: Initializing cache
May 22 22:07:51: SYS_OBJ: #0 not found
May 22 22:07:51: SYS_OBJ: #0 not found
Object #1 programmed.
Object #0 programmed.
Object #2 programmed.
Object #3 programmed.
Object #4 programmed.
Object #5 programmed.
Object #6 programmed.
Object #7 programmed.
Object #8 programmed.
Object #9 programmed.
Object #10 programmed.
Object #11 programmed.
Object #12 programmed.
Object #13 programmed.
Object #14 programmed.
Object #15 programmed.
May 22 22:07:51: Syncing cache
May 22 22:07:51: Closing database
rm -f west.tmp
rm -f east.tmp
for file in bin/root_obj.cl bin/sys_obj.cl bin/located_obj.cl bin/described_obj.cl bin/thing.cl bin/container.cl bin/room.cl bin/exit.cl bin/player.cl bin/builder.cl bin/programmer.cl bin/wizard.cl bin/east.cl; do gcc -E -P -x c $file >> east.tmp; done
bin/cm.exe bin/east -i -f east.tmp
May 22 22:07:51: Reading config file from bin/east.cfg
May 22 22:07:51: Cache depth starts at 23 slots.
May 22 22:07:51: Cache width is 7 slots.
May 22 22:07:51: Initializing db
May 22 22:07:51: Initializing cache
May 22 22:07:51: SYS_OBJ: #0 not found
May 22 22:07:51: SYS_OBJ: #0 not found
Object #1 programmed.
Object #0 programmed.
Object #2 programmed.
Object #3 programmed.
Object #4 programmed.
Object #5 programmed.
Object #6 programmed.
Object #7 programmed.
Object #8 programmed.
Object #9 programmed.
Object #10 programmed.
Object #11 programmed.
Object #12 programmed.
Object #13 programmed.
Object #14 programmed.
May 22 22:07:51: Syncing cache
May 22 22:07:51: Closing database
rm -f east.tmp
[me@localhost coolmud]$ cd bin
[me@localhost bin]$ ./cm.exe west &
[1] 12432
[me@localhost bin]$ May 22 22:07:59: Reading config file from west.cfg
May 22 22:07:59: Cache depth starts at 23 slots.
May 22 22:07:59: Cache width is 7 slots.
May 22 22:07:59: Initializing db
May 22 22:07:59: Initializing cache
May 22 22:07:59: Initializing sockets.
May 22 22:07:59: Connecting to remote servers.
May 22 22:07:59: Server initialized.
telnet 0 7777
Trying 0.0.0.0…
Connected to 0.
May 22 22:08:06: Escape character is '^]'.
Accepted player from 127.0.0.1(-24871)
*** WELCOME TO COOLMUD WEST! ***
COOLMUD created by Stephen White.
Use "create <name> <password>" to create a new character.
Use "connect <name> <password>" to connect to an existing character.
create new character
May 22 22:08:10: Player created: new(#16) on descriptor 7
*** Connected ***
You're absolutely nowhere. Go home.
@spew init on #7
THIS OBJPUSH 7 0 EQ IF 17 81 THIS OBJPUSH 11 0 MESSAGE 1 "add_owner" POP STOP CALLER THIS EQ OR 26 CALLER GETGVAR owners IN ENDOR OR 0 CALLER PARENTS IN ENDOR OR 40 CALLER OBJPUSH 0 0 EQ ENDOR OR 51 CALLER OBJPUSH 0 0 MESSAGE 0 "wizards" IN ENDOR OR 57 GETGVAR owners NOT ENDOR ELSEIF 75 OBJPUSH -1 0 ASGNGVAR source OBJPUSH -1 0 ASGNGVAR dest PASS 0 3 POP STOP ELSE ERRPUSH 10 RAISE STOP STOP STOP
{ machine[yyvsp[-1].num + 1] = code(ENDOR); // This writes the location of ENDOR to the byte following OR
#include <stdlib.h>
#include <stdio.h>
#define CODE_INIT_SIZE 32
int *machine;
int progi, machine_size;
void code_init (void)
{
machine_size = CODE_INIT_SIZE;
machine = (int*) malloc (sizeof(int) * machine_size);
progi = 0;
}
int code (int inst)
{
int *new_machine;
int i;
if (!machine || !machine_size) {
code_init ();
}
if (progi >= machine_size) {
machine_size *= 2;
new_machine = (int*) malloc (sizeof(int) * machine_size);
for (i = 0; i < progi; i++) {
new_machine[i] = machine[i];
}
free (machine);
machine = new_machine;
}
machine[progi++] = inst;
return progi - 1;
}
int main() {
int i;
code(0);
for (i=0;i<100;i++) {
if (i<30)
machine[i] = 0;
else
machine[i-30] = code(0);
}
for (i=0;i<100;i++)
printf("%d ", machine[i]);
return 0;
}
#include <stdlib.h>
#include <stdio.h>
int* bar;
int foo ()
{
bar = (int*) malloc (sizeof(int) * 10);
return 99;
}
int main() {
bar[0] = foo();
printf("%d ", bar[0]);
return 0;
}
$ gcc-3 testcode2.c
$ ./a
99
$ gcc-4 testcode2.c
$ ./a
Segmentation fault (core dumped)
>bcc32 testcode2.c
Embarcadero C++ 6.30 for Win32 Copyright © 1993-2010 Embarcadero Technologies, Inc.
testcode2.c:
Warning W8065 testcode2.c 12: Call to function 'foo' with no prototype in function main
Turbo Incremental Link 6.10 Copyright © 1997-2010 Embarcadero Technologies, Inc.
>testcode2
99
>bcc32 testcode2.c
Borland C++ 5.5.1 for Win32 Copyright © 1993, 2000 Borland
testcode2.c:
Warning W8065 testcode2.c 12: Call to function 'foo' with no prototype in function main
Turbo Incremental Link 5.00 Copyright © 1997, 2000 Borland
>testcode2
99
>cl testcode2.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
testcode2.c
Microsoft (R) Incremental Linker Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
/out:testcode2.exe
testcode2.obj
>testcode2
99
>cl testcode2.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
testcode2.c
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
/out:testcode2.exe
testcode2.obj
>testcode2
99
>dmc testcode2
Digital Mars Compiler Version 8.42n
Copyright (C) Digital Mars 2000-2004. All Rights Reserved.
link testcode2,,,user32+kernel32/noi;
>testcode2
99
>lcc -v
Logiciels/Informatique lcc-win32 version 3.8. Compilation date: Nov 24 2011 14:39:47
>lcc testcode2.c
Warning testcode2.c: 12 Missing prototype for 'foo'
0 errors, 1 warning
>testcode2
99
int balloons = 77;Kate from ##C helped me to strip it down to this test-case.
int *bar;
int foo( void );
int foo( void )
{
bar = &balloons;
return 99;
}
int main( void )
{
*bar = foo( );
return *bar;
}
#include <stdlib.h>I don't know whether it's the compiler violating the standard or the code relies on unspecified/undefined behavior. One thing is solved, I believe: it can be circumvented as shown above.
#include <stdio.h>
int* bar;
int foo ()
{
bar = (int*) malloc (sizeof(int) * 10);
return 99;
}
int main() {
int temp = foo();
bar[0] = temp;
printf("%d ", bar[0]);
return 0;
}
bar[0] = (int) foo();
You can find it in the Tiny area of the code repository.
However I can across a runtime bug that shows up only when using gcc 4.x compilers. The code works perfectly
under gcc 3.x, Digital Mars, Borland 5.5 and 6.3, and all versions of Visual C from v6.0 to the new beta 2011.
I was unable to figure it out, but I was able to work around it.
The problem is this. CoolMud has it's own mud programming language which compiles to byte code which runs
on a virtual machine. The CoolMud compiler spits out an invalid code under certain conditions with gcc4 regardless of
whether I'm using yacc, byacc, or bison.
Here's an example. You can dump the bytecode of methods inside the mud using the @spew command.
Server compiled with gcc 3.3
@spew init on #7
THIS OBJPUSH 7 0 EQ IF 17 81 THIS OBJPUSH 11 0 MESSAGE 1 "add_owner" POP STOP CALLER THIS EQ OR 26 CALLER GETGVAR owners IN ENDOR OR 32 CALLER PARENTS IN ENDOR OR 40 CALLER OBJPUSH 0 0 EQ ENDOR OR 51 CALLER OBJPUSH 0 0 MESSAGE 0 "wizards" IN ENDOR OR 57 GETGVAR owners NOT ENDOR ELSEIF 75 OBJPUSH -1 0 ASGNGVAR source OBJPUSH -1 0 ASGNGVAR dest PASS 0 3 POP STOP ELSE ERRPUSH 10 RAISE STOP STOP STOP
Server compiled with gcc 4.4.1
@spew init on #7
THIS OBJPUSH 7 0 EQ IF 17 81 THIS OBJPUSH 11 0 MESSAGE 1 "add_owner" POP STOP CALLER THIS EQ OR 26 CALLER GETGVAR owners IN ENDOR OR 0 CALLER PARENTS IN ENDOR OR 40 CALLER OBJPUSH 0 0 EQ ENDOR OR 51 CALLER OBJPUSH 0 0 MESSAGE 0 "wizards" IN ENDOR OR 57 GETGVAR owners NOT ENDOR ELSEIF 75 OBJPUSH -1 0 ASGNGVAR source OBJPUSH -1 0 ASGNGVAR dest PASS 0 3 POP STOP ELSE ERRPUSH 10 RAISE STOP STOP STOP
Note how the instruction following the OR instruction is a 0 with gcc4 but with gcc3 is a 32, which is correct.
The instruction following the OR is a jump address relative to start of the bytecode. It is filled in with the address
of the next ENDOR operand at the time the ENDOR opcode is encountered.
The same error occurs with the AND opcode on object #7 method match.
@spew match on #7 to see it.
Here's the generated parser code from YACC with my comments:
case 124:
#line 392 "src/cool.y"
{ yyval.num = code2(AND, 0); }
break;
case 125:
#line 393 "src/cool.y"
{ machine[yyvsp[-1].num + 1] = code(ENDAND); // This writes the location of ENDAND to the byte following AND
yyval.num = yyvsp[-3].num; }
break;
case 126:
#line 395 "src/cool.y"
{ yyval.num = code2(OR, 0); }
break;
case 127:
#line 396 "src/cool.y"
{ machine[yyvsp[-1].num + 1] = code(ENDOR); // This writes the location of ENDOR to the byte following OR
yyval.num = yyvsp[-3].num; }
break;
ENDOR and ENDAND are null opcodes. The purpose is to jump to process the next boolean expression.
In all cases this happens when the jump location is exactly 32. 32 happens to be the initial size allocated
to the virtual machine, and it reallocates a double amount each time you run out of room.
Here's a link to the repository code that allocates the virtual machine.
http://sourcery.dyndns.org/svn/coolmud/t...
I've looked, traced, set watches and looked again and I just can't find the problem.
My workaround was to change CODE_INIT_SIZE to 4096 from 32. If I do that the problem disappears, but I suspect
would reappear if the method generated a large amount of bytecode.
The really really odd thing is there are no compiler warnings in regards to this and it works in every other compiler save gcc 4.x.
And this happens with both 32-bit and 64-bit gcc 4.x compilers on Cygwin and on native Linuxes.
Any ideas?