PDA

Ver la Versión Completa : Problema de memoria...


Xianto
28-01-2005, 15:33:26
Buenas...

Debido a una necesidad personal he hecho una app para que busque y reemplaze texto en archivos de manera recursiva en un directorio o varios...

Para probarlo descomprimi en un dir un php-nuke completo, y luego con el programilla intente cambiar en todos los archivos y todas las carpetas lo que dijera "php" por "pepino" y funciono muy bien, luego al intentar nuevamente cambiar "pepino" por "meduza" me da el tipico error de memoria.

Entonces busque los create para liberarlos, pero todo estaba bien... al ser solo un formulario no uso nada extraño, ya que solo es un form.
Lo interesante es que cierro la app la abro, cambio en ese mismo dir "pepino" por "meduza", luego voy a otro dir distinto y cambio "pepe" por "pepa" y no me da fallos...

La verdad es que estoy perdido, intente buscar la linea donde da el fallo, pero es imposible, ya que en una funcion recursiva de busquedad de todos los archivos llega a unos 5621 carpetas y tengo que estar con el F8 hasta que llegue a esa linea que me da problema, porque sino al fallar me aparece el debug de memoria...

He aquí la función en discordia:


procedure TForm1.Rastrear(dir: string);
var
sr: TSearchRec;
begin
if FindFirst (Dir+'\*.*', faDirectory, sr)=0 then
begin
while FindNext(sr)=0 do
If (((sr.Attr and faArchive) <> 0) and (Pos(st, sr.Name)>0)) then
begin
FList.Add(Dir+'\'+sr.Name);
tempo := tempo + 1;
Label4.Caption := 'Archivos hallados: ' + IntToStr(tempo);
end;
Application.ProcessMessages;
IPosi := IPosi + -1;
FindClose(sr);
If IPosi > -1 Then
Rastrear(DList[IPosi]);
end;
end;


No se, alguna idea de lo que puedo mirar ???

mamcx
28-01-2005, 16:23:24
Has probado con un chequeador de Leaks como MemProof (gratis) o AQTime? Podria ser fragmentacion de memoria on un leak...

Estas seguro que es MEMORIA? No sera un asunto de encoding? Mencionas que lees archivos de texto de PHP Nuke y usas FList.Add. que supongo es un TStringList.... que usa Strings ANSI, y TAL VEZ estas cargando un archivo UNICODE con un encoding como UTF-8 u otro?

Ademas, cual tipico error de memoria, seria bueno bueno saber...

Ah... te recomiendo que uses algo como http://www.eurekalog.com/ para tener mejor informacion de los errores, junto al call stack, linea de error y demas....

Xianto
28-01-2005, 16:57:01
wenas... gracias por tu respuesta... mirare lo que me dices.

el error, al ejecutar el exe, sin el delphi... es: Stack Overflow

jejeje, un bonito error !

Nota:

El TStringList, lo uso para guardar la ruta de cada archivo, ejemplo:

C:\php-nuke\administrator\pepe.php
C:\php-nuke\administrator\pepa.php
C:\php-nuke\admin.php

Y asi, de esta forma en un TList tengo todos los archivos del directorio inicial, incluyendo todos los sub-directorios en una lista... y luego con otra funcion recursiva son leidos y analizados, para ver si contienen el patron utilizado... ahi es donde me sirve el TList, aunque en algunos casos llega a tener 8000 lineas o mas... depende lo que busques.
Para abrir los ficheros segun la extension que elijas, uso FileOpen y FileSeek. Y para cambiar el texto uso AnsiReplaceText...

Bue, sigo mirando !

Xianto
28-01-2005, 17:30:34
Ufffffffff.... vaya tonteria... aumente el Stack Size y listo... es lo que pasa con las funciones recursivas...

Max Stack Size = $00400000

Aunque baje el visor de problemas en http://www.eurekalog.com/ y resulta que es muy util... gracias por la info !


Saludetes !!!!

mamcx
28-01-2005, 17:40:24
Pero eso no es una solucion. Si la cantidad de directorios se duplica, no te volvera a pasar?

Me parece que cargas demasiado en el TStringList. Deberias, en mi opinion, hacer la parte de chequear si cumple o no con el patron directamente en el escaneo y no darle dos pasadas.

Xianto
28-01-2005, 22:28:57
Cierto... mirare un poco a ver si lo resuelvo quitando un poco de lienas del TList... pero sigo pensando que de cualquier manera necesito tener muchas lineas...

La otra opcion es usar un array que ocupa menos memoria que la TList...

Mick
28-01-2005, 23:07:36
Cierto... mirare un poco a ver si lo resuelvo quitando un poco de lienas del TList... pero sigo pensando que de cualquier manera necesito tener muchas lineas...

La otra opcion es usar un array que ocupa menos memoria que la TList...

El tamaño de un tlist no es un problema , por muy grande que sea no te va a dar nunca un Stack Overflow te podria dar un error de falta de memoria pero no especificamente "Stack Overflow".
Ademas un TList con decenas o cientos de miles de elementos no es nada para cualquier computadora normal.

El problema es la llamada recursiva a la funcion, por cada llamada se ocupan 4 bytes de la pila.

Ese algoritmo no es correcto, te basta un bucle normal sin recursividad para recorrer la lista.

Un bucle normal aunque se ejecute millones de veces ocupa 0 de memoria, en cambio un millon de llamadas recursivas ocuparian 4 millones de bytes en la pila.

Saludos