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

Reply via email to