As requested, I wrote a nasty little recursive program to test
strings, memory and call stacks. Immediately bad stuff happened
when the stack frames outgrew a single chunk and a new one was
allocated. When the frame stack reached FRAMES_PER_CHUNK,
the new chunk gets allocated, etc, etc. and bad stuff happened after
a pop*.
I traced it down to push* copying the register frame onto the previous
stack chunk, not the new stack chunk. The following patch fixes,
I went ahead and committed because seg faults are bad. :)
Afterwards the test program ran with larger file sizes, eventually
crashing again, but this time in the GC. <*PUNT* Dan goes back to the 10
yard line.....>
../parrot reverse.pbc < string.c
<file prints out pre-reverse call>
recurse depth 0
Segmentation fault (core dumped)
:)
So the nasty test prog has done its duty for tonite, putting it to bed.
Patch follows, then the test program.
Index: register.c
===================================================================
RCS file: /cvs/public/parrot/register.c,v
retrieving revision 1.19
diff -u -r1.19 register.c
--- register.c 5 Mar 2002 05:30:17 -0000 1.19
+++ register.c 26 Mar 2002 07:30:10 -0000
@@ -30,7 +30,7 @@
else {
struct IRegChunk *new_chunk;
new_chunk = mem_sys_allocate(sizeof(struct IRegChunk));
- memcpy(&interpreter->int_reg_top->IReg[0],
+ memcpy(&new_chunk->IReg[0],
&interpreter->int_reg, sizeof(struct IReg));
new_chunk->used = 1;
new_chunk->free = FRAMES_PER_INT_REG_CHUNK - 1;
@@ -101,7 +101,7 @@
else {
struct SRegChunk *new_chunk;
new_chunk = mem_sys_allocate(sizeof(struct SRegChunk));
- memcpy(&interpreter->string_reg_top->SReg[0],
+ memcpy(&new_chunk->SReg[0],
&interpreter->string_reg, sizeof(struct SReg));
new_chunk->used = 1;
new_chunk->free = FRAMES_PER_STR_REG_CHUNK - 1;
@@ -171,7 +171,7 @@
else {
struct NRegChunk *new_chunk;
new_chunk = mem_sys_allocate(sizeof(struct NRegChunk));
- memcpy(&interpreter->num_reg_top->NReg[0],
+ memcpy(&new_chunk->NReg[0],
&interpreter->num_reg, sizeof(struct NReg));
new_chunk->used = 1;
new_chunk->free = FRAMES_PER_NUM_REG_CHUNK - 1;
@@ -241,7 +241,7 @@
else {
struct PRegChunk *new_chunk;
new_chunk = mem_sys_allocate(sizeof(struct PRegChunk));
- memcpy(&interpreter->pmc_reg_top->PReg[0],
+ memcpy(&new_chunk->PReg[0],
&interpreter->pmc_reg, sizeof(struct PReg));
new_chunk->used = 1;
new_chunk->free = FRAMES_PER_PMC_REG_CHUNK - 1;
reverse.cola (slurps in a file, then recursively swaps string 1/2s until whole
buffer is reversed, then prints). Works ok on files up to 20k, then barfs
with the
stack trace at the end.
// reverse.cola
//
// Reverse an input string recursively swapping.
// Give it a bigger file to make the GC grind and the
// call stack grow. :)
//
using System;
public class Reverse {
// Recursively reverse string halves until halves are length 1
public string Reverse(string s1, string s2, int d) {
int len = strlen(s1);
puts("recurse depth ");
puti(d);
puts("\n");
if(len > 1)
s1 = Reverse(substr(s1, 0, len/2), substr(s1, len/2,
len-len/2), d + 1);
len = strlen(s2);
if(len > 1)
s2 = Reverse(substr(s2, 0, len/2), substr(s2, len/2,
len-len/2), d + 1);
//puts("(" + s1 + ")(" + s2 + ")\n");
return s2 + s1;
}
public static void Main() {
string str, bstr;
while(1) {
bstr = gets();
if(bstr == "")
break;
puts(bstr);
str = str + bstr;
}
//puts(bstr);
// Reverse it with recursion
puts("\n");
// Reverse the 2 halves
str = Reverse(str, "", 0);
puts(str);
}
}
***Stack trace***
(gdb) back
#0 0x4012efef in memcpy (dstpp=0x402ae750, srcpp=0x40255dc0, len=15872)
at ../sysdeps/generic/memcpy.c:55
#1 0x0809311f in Parrot_go_collect (interpreter=0x8170d78) at resources.c:738
#2 0x080933bf in Parrot_allocate (interpreter=0x8170d78, size=11456)
at resources.c:848
#3 0x0808e6c5 in Parrot_string_make (interpreter=0x8170d78, buffer=0x0,
buflen=11449, encoding=0x80aefc0, flags=0, type=0x80af388) at string.c:50
#4 0x0808ef4d in Parrot_string_substr (interpreter=0x8170d78, src=0x818cf50,
offset=0, length=11449, d=0x8170f70) at string.c:396
#5 0x0805466d in Parrot_substr_s_s_i_i (cur_opcode=0x818db4c,
interpreter=0x8170d78) at core.ops:1539
#6 0x0808fb5f in runops_fast_core (interpreter=0x8170d78, pc=0x818db4c)
at runops_cores.c:30
#7 0x0804940e in runops_generic (core=0x808fb30 <runops_fast_core>,
interpreter=0x8170d78, pc=0x818d768) at interpreter.c:77
#8 0x08049cc5 in runops (interpreter=0x8170d78, code=0x818d6d8, offset=0)
at interpreter.c:463
#9 0x08093ff6 in Parrot_runcode (interpreter=0x8170d78, argc=1,
argv=0xbffffb18) at embed.c:213
#10 0x080a08de in main (argc=1, argv=0xbffffb18) at test_main.c:48
#11 0x400c7306 in __libc_start_main (main=0x80a084c <main>, argc=2,
ubp_av=0xbffffb14, init=0x8048dc4 <_init>, fini=0x80a0b70 <_fini>,
rtld_fini=0x4000d2cc <_dl_fini>, stack_end=0xbffffb0c)
at ../sysdeps/generic/libc-start.c:129
(gdb)
-Melvin