Autor Tema: Me la peta (la memoria ja ja)  (Leído 1418 veces)

Danielo515

  • Sr. Member
  • ****
  • Mensajes: 480
  • Karma: 4
    • Blog del Blogbo
Me la peta (la memoria ja ja)
« en: Junio 17, 2009, 04:11:47 pm »
Bueno, antes de nada, uno de mis fetiches, además de programar para hardware obsoleto, es hacer programas estúpidos, absurdos y lo más recursivos posibles. Dicho esto, os explico lo que hace este programa: cada proceso, llama con los parametros que devuelve glob a un proceso que si es un directorio, llama a su vez a otros procesos igual que el que harán lo mismo si son directorios.

El problema es que cuando hay mucha profundidad de carpetas, acaba violando la memoria en algún lugar y por algún motivo.
Otro problema que tengo, que ya lo resolveré más adelante, es organizarlo de forma que entre todo en pantalla, pero eso es otra historia. ahí va el programa
[code language="bennu"]
import "mod_draw";
import "mod_text";
import "mod_key";
import "mod_proc";
import "mod_string";
import "mod_dir";
//

global
g_x;
g_y;
string filename;
private
dirs;
sub_d;
colores[3];
i;
begin
drawing_map(0,0);
drawing_color(rgb(255,0,0));
set_mode(1024,1024,8);

colores[0]=rgb(255,0,0);
colores[1]=rgb(0,255,0);
colores[2]=rgb(0,0,255);
colores[3]=rgb(255,255,255);

while( (filename=Glob("*")) != "")
   if(fileinfo.directory==1)
   dirs++;
   end//if
end

frame; //importante para reiniciar glob

while( (filename=Glob("*")) != "")
   if(filename!="." and filename!=".." and fileinfo.directory==1)
       g_y+=600/dirs;
       sub(fileinfo.name,fileinfo.path,fileinfo.directory,10,g_y,colores);
      i++;
      if(i>3) i=0; end
   end//if
end
g_x=0;

end



process sub(string me,string pat,int directorio, int x,int y,color)
private
string filename;
xx;
yy;
hijos;
begin
drawing_color(color);

frame;
if(directorio==1)
   graph=write_in_map(0,"DIR",4);
   
while((filename=glob(pat+me+"\*"))!="")
    if(filename!="." and filename!="..")
      hijos++;
   end//if
   end//while
   
frame;
yy=y-((hijos/2)*10);   
 while((filename=glob(pat+me+"\*"))!="")
    if(filename!="." and filename!="..")
      if(fileinfo.directory==1)   
           sub(fileinfo.name,fileinfo.path,fileinfo.directory,x+200,yy,color);
           yy+=30;
        else
           sub(fileinfo.name,fileinfo.path,fileinfo.directory,x+150,yy,color);
           yy+=10;
        end
        
       draw_line(x,y,son.x,son.y);
       yy+=10;
   end//if
   end//while
   
else
   graph=write_in_map(0,"F",3);
end

repeat
frame;
until(key(_esc))

end[/code]

SplinterGU

  • Hero Member
  • *****
  • Mensajes: 12887
  • Karma: 377
Re: Me la peta (la memoria ja ja)
« Respuesta #1 en: Junio 17, 2009, 05:36:11 pm »
La funcion glob no es recursiva.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Danielo515

  • Sr. Member
  • ****
  • Mensajes: 480
  • Karma: 4
    • Blog del Blogbo
Re: Me la peta (la memoria ja ja)
« Respuesta #2 en: Junio 17, 2009, 06:57:18 pm »
Ya se que no es recursiva splinter. Pero cada proceso la llama con un patrón distinto correspondiente a una subcarpeta cada uno, así que de eso no te preocupes, que funcionar funciona, lo que no se es porque me viola la memoria.

SplinterGU

  • Hero Member
  • *****
  • Mensajes: 12887
  • Karma: 377
Re: Me la peta (la memoria ja ja)
« Respuesta #3 en: Junio 17, 2009, 10:05:58 pm »
Eso es lo que no funciona.

No podes cortar la busqueda en mitad para empezar otra y luego continuar la anterior. No se puede, no es recursiva. Por eso puede ser que te viola la memoria.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

  • Hero Member
  • *****
  • Mensajes: 12887
  • Karma: 377
Re: Me la peta (la memoria ja ja)
« Respuesta #4 en: Junio 18, 2009, 04:13:12 am »
ajap, ya veo algunas cosas que estas haciendo mal...

glob no se reinicia con frame.

glob se reinicia con cada string diferente que le pasas de patron de busqueda.
sin necesidad de conocer como funciona internamente, nos detenemos a pensar un momento y consideramos en los parametros que recibe, lo que devuelve llamada tras ejecucion, nos daremos cuenta que hay un contexto interno que indica el patron a buscar y el ultimo patron utilizado para saber si debemos o no reiniciar la busqueda, por consiguiente nos daremos cuenta que no es recursiva, y que el empleo que le das es incorrecto.
El ejemplo, que planteas arriba, solo muestra un nivel de profundidad de directorio.

No creo que nada de esto se deba al cuelgue que te provoca la ejecucion de este codigo, creo que el cuelgue estan en las primeras lineas, en la parte grafica.

Luego lo debugueare... gracias por el ejemplo.

Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Danielo515

  • Sr. Member
  • ****
  • Mensajes: 480
  • Karma: 4
    • Blog del Blogbo
Re: Me la peta (la memoria ja ja)
« Respuesta #5 en: Junio 18, 2009, 10:07:44 am »
Vale, eso no lo sabía, una cosa nueva para mi coco. Yo creia que se reiniciaba con frame. Teniendo en cuenta eso, de todos modos funcionar debería funcionar, porque cada proceso llama a la función glob con una string distinta, ya que cada proceso corresponde a un directorio distinto. Lo que no debería funcionar es lo de contar los hijos de cada función, pero aparentemente funciona.

Es decir, yo entiendo que glob no es recursiva, pero también entiendo que el modo en el que la uso es el correcto para hacer lo que busco, y si que funciona para varias profundidades de directorios, porque lo he probado y cuando lleva tres o cuatro niveles es cuando viola la memoria.

Un saludo.

SplinterGU

  • Hero Member
  • *****
  • Mensajes: 12887
  • Karma: 377
Re: Me la peta (la memoria ja ja)
« Respuesta #6 en: Junio 18, 2009, 11:50:17 am »
no, diablos! no es correcto... bueno, funciona a medias, pero de casualidad, ya que basado en que vos pensabas que frame reseteaba el glob, entonces no deberia funcionar... ya que entrarias, frame resetearia, y luego al retornar al padre, ya la busqueda del padre dejaria de existir... y funciona contrariamente gracias a ese frame que tenes al inicio de sub... si no lo tuvieras no funcionaria... ya que el padre esta en un glob, llama a un hijo que hace otro glob diferente (en este momento el glob del padre es destruido) cuando el hijo retorna del padre, el padre al intentar seguir con su glob, lo unico que logra hacer es un nuevo glob, con lo que reinicia nuevamente toda la secuencia obteniendo el nombre de su glob.

Ahora como vos tenes un frame, funciona, pero no funciona bien, por varios motivos:

1) te falta en el directorio inicial, poner la "/" del path.
2) tenes un while con glob y un frame demas, lo cual hace que el orden que se muestren los datos sea totalmente desordenado (aunque tampoco es 100% ordenado como para hacer lo que pretendes hacer, yo te diria que guardes todo en un array, lo ordenes, y luego lo dibujes en pantalla)
3) cuando entra a sub y no es directorio, tu intencion es mostrar el archivo, pero por todo esto que te digo no lo muestra, ya que el glob correspondiente a dicha llamada fue destruido... y lo correcto es imprimir "pat + me"... sin embargo imprime "."

Aca modifique un poco tu codigo para hacerlo funcionar correctamente y le agregue info de debug... retire todo lo que corresponde a draw, asi podes apreciar como funciona, espero que esta vez se haya entendido...

Código: [Seleccionar]
import "mod_string";
import "mod_dir";
import "mod_say";

global
    string filename;

begin

say ("-----------------");

    while ( (filename = Glob("*")) != "")
        if (filename != "." and filename != ".." and fileinfo.directory == 1)
            say (filename);
            sub(fileinfo.name, fileinfo.path + "/", fileinfo.directory);
        end //if
    end

end



process sub(string me, string pat, int directorio)
private
    string filename;
    xx;
    yy;
begin
    frame;
    if (directorio == 1)
        say("--- dir ---> " + pat + me );
        while ((filename = glob(pat + me + "/*")) != "")
            if (filename != "." and filename != "..")
                say ("F:"+filename);
                if (fileinfo.directory == 1)
                    sub(fileinfo.name, fileinfo.path, fileinfo.directory);
                else
                    sub(fileinfo.name, fileinfo.path, fileinfo.directory);
                end
            end //if
        end //while

    else
        say ("File ("+pat+me+"):"+fileinfo.path + fileinfo.name);
    end
end

estructura de directorio usada para la prueba
Citar
splinter@splinter:~/Bennu/bugs/glob$ ls -lrt
total 28
drwxr-xr-x 4 splinter splinter  4096 jun 18 08:02 sdir1
-rw-r--r-- 1 splinter splinter  1069 jun 18 08:48 glob.prg
-rw-r--r-- 1 splinter splinter 17503 jun 18 08:48 glob.dcb
splinter@splinter:~/Bennu/bugs/glob$ ls -lR
.:
total 28
-rw-r--r-- 1 splinter splinter 17503 jun 18 08:48 glob.dcb
-rw-r--r-- 1 splinter splinter  1069 jun 18 08:48 glob.prg
drwxr-xr-x 4 splinter splinter  4096 jun 18 08:02 sdir1

./sdir1:
total 8
-rw-r--r-- 1 splinter splinter    0 jun 18 08:02 file1
drwxr-xr-x 3 splinter splinter 4096 jun 18 08:02 sdir1.1
drwxr-xr-x 2 splinter splinter 4096 jun 18 08:15 sdir1.2

./sdir1/sdir1.1:
total 4
-rw-r--r-- 1 splinter splinter    0 jun 18 08:02 file1.1
drwxr-xr-x 2 splinter splinter 4096 jun 18 08:02 sdir1.1.1

./sdir1/sdir1.1/sdir1.1.1:
total 0
-rw-r--r-- 1 splinter splinter 0 jun 18 08:02 file1.1.1

./sdir1/sdir1.2:
total 0
-rw-r--r-- 1 splinter splinter 0 jun 18 08:15 file1.2

Resultados obtenidos
Citar
splinter@splinter:~/Bennu/bugs/glob$ bgdi glob
-----------------
sdir1
--- dir ---> /home/splinter/Bennu/bugs/glob/sdir1
F:sdir1.2
F:file1
F:sdir1.1
--- dir ---> /home/splinter/Bennu/bugs/glob/sdir1/sdir1.1
F:file1.1
F:sdir1.1.1
File (/home/splinter/Bennu/bugs/glob/sdir1/file1):/home/splinter/Bennu/bugs/glob/sdir1/sdir1.1/.
--- dir ---> /home/splinter/Bennu/bugs/glob/sdir1/sdir1.2
F:file1.2
File (/home/splinter/Bennu/bugs/glob/sdir1/sdir1.2/file1.2):/home/splinter/Bennu/bugs/glob/sdir1/sdir1.2/.
--- dir ---> /home/splinter/Bennu/bugs/glob/sdir1/sdir1.1/sdir1.1.1
F:file1.1.1
File (/home/splinter/Bennu/bugs/glob/sdir1/sdir1.1/file1.1):/home/splinter/Bennu/bugs/glob/sdir1/sdir1.1/sdir1.1.1/.
File (/home/splinter/Bennu/bugs/glob/sdir1/sdir1.1/sdir1.1.1/file1.1.1):/home/splinter/Bennu/bugs/glob/sdir1/sdir1.1/sdir1.1.1/.
« última modificación: Junio 18, 2009, 11:54:14 am por SplinterGU »
Download Lastest BennuGD Release: http://www.bennugd.org/node/2