Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus-es / 2016-07

uso de SetLength

14 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Rafael Bidegain
A propósito del tema planteado por Juan M. Puertas y el aporte realizado
por Jesus Reyes A.
Me ha llamado la atención el uso de la función SetLength en la función
vbSplit.
function vbSplit(S: string; Delimiter: char): TStrArray;
var
  C: integer;
begin
  repeat
    SetLength(Result, Length(Result) + 1);
    C := Pos(Delimiter, S);
    if C = 0 then
      C := Length(S) + 1;
    Result[Length(Result) - 1] := Copy(S, 1, C - 1);
    Delete(S, 1, C);
  until Length(S) = 0;
end;

Yo creo que en esa función el programador asumió que SetLength siempre expandirá el array.
Según mis pocos conocimientos para que eso sea posible, en tiempo de compilación, se debería reservar una cantidad importante de memoria contigua para el posible crecimiento de cada array dinamico que el programador declare o
implementar en SetLength una opción para mover el array a otra zona si no hay espacio disponible.
en C se resolvería llamando a realloc

pero en la documentación no entiendo eso. yo entiendo que se debe llamar _una vez_ a SetLength con un valor mayor a cero y otra vez con valor igual a cero si se desea borrar los datos del array.
http://www.freepascal.org/docs-html/rtl/system/setlength.html

¿qué opinan uds?

Rafael Bidegain Ya que los cuerdos no hablan, hablará el loco. (The Fool, Padraic Pearse) # yo quiero educación libre. ¡YA! ------------ próxima parte ------------ Se ha borrado un adjunto en formato HTML... URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160720/ed943939/attachment.html>

Reply by email

Jesus Reyes A.
to Rafael Bidegain

En Tue, 19 Jul 2016 23:14:23 -0500, Rafael Bidegain <r.bidegain en gmail.com>

Show quoted text 20 lines
A propósito del tema planteado por Juan M. Puertas y el aporte realizado por Jesus Reyes A. Me ha llamado la atención el uso de la función SetLength en la función vbSplit. function vbSplit(S: string; Delimiter: char): TStrArray; var C: integer; begin repeat SetLength(Result, Length(Result) + 1); C := Pos(Delimiter, S); if C = 0 then C := Length(S) + 1; Result[Length(Result) - 1] := Copy(S, 1, C - 1); Delete(S, 1, C); until Length(S) = 0; end; > Yo creo que en esa función el programador asumió que SetLength siempre > expandirá el array.

Y así es, de lo contrario debería arrojar un error que en este caso particular no es manejado.

Show quoted text 6 lines
Según mis pocos conocimientos para que eso sea posible, en tiempo de compilación, se debería >reservar una cantidad importante de memoria contigua para el posible crecimiento de cada array >dinamico que el programador declare oimplementar en SetLength una opción para mover el array a otra zona si no hay espacio disponible. en C se resolvería llamando a realloc

De esto se encarga FPC. Si SetLength no falla, esta garantizado que la memoria reservada para el array es un segmento continuo de memoria. Internamente FPC se encarga de que todos los detalles para que esto sea así. No por nada se les llama Arrays Dinámicos :).

Show quoted text 5 lines
> pero en la documentación no entiendo eso. yo entiendo que se debe > llamar _una vez_ a SetLength con >un valor mayor a cero y otra vez con > valor igual a cero si se desea borrar los datos del array. http://www.freepascal.org/docs-html/rtl/system/setlength.html

He leído el artículo enlazado y la lectura que hago no me dice nada a cerca de que se *deba* usa solo una vez, y si no lo dice es por que no es así, puedes usar SetLength las veces que sea necesario. Y si en algún punto quieres tener la conciencia tranquila con respecto a la memoria reservada dinámicamente puedes especificar 0 como número de elementos y eso "limpiara" el array, aquí cleared se usa para indicar que la memoria usada por el array será liberada.

Lo que no dice es que aumentar el número de elementos del array no "elimina" los elementos existentes, sino que solo hace más espacio para la cantidad extra deseada de elementos. De nuevo internamente FPC hace todo lo necesario para que al final todos los elementos del array estén dentro de un segmento continuo de memoria.

> ¿qué opinan uds? >>

Saludos.

Jesus Reyes A.
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160720/06feeb8f/attachment.html>

Reply by email

Juan M. Puertas
to Jesus Reyes A.

Gracias Rafael y Jesús.
Buscaré información sobre cómo cambiar esta función para que haga correctamente el uso de SetLength.
Saludos :-)

Jesus Reyes A. wrote 78 lines
En Tue, 19 Jul 2016 23:14:23 -0500, Rafael Bidegain <r.bidegain en gmail.com> escribió: A propósito del tema planteado por Juan M. Puertas y el aporte realizado por Jesus Reyes A. Me ha llamado la atención el uso de la función SetLength en la función vbSplit. function vbSplit(S: string; Delimiter: char): TStrArray; var C: integer; begin repeat SetLength(Result, Length(Result) + 1); C := Pos(Delimiter, S); if C = 0 then C := Length(S) + 1; Result[Length(Result) - 1] := Copy(S, 1, C - 1); Delete(S, 1, C); until Length(S) = 0; end; Yo creo que en esa función el programador asumió que SetLength siempre expandirá el array. Y así es, de lo contrario debería arrojar un error que en este caso particular no es manejado. Según mis pocos conocimientos para que eso sea posible, en tiempo de compilación, se debería reservar una cantidad importante de memoria contigua para el posible crecimiento de cada array dinamico que el programador declare o implementar en SetLength una opción para mover el array a otra zona si no hay espacio disponible. en C se resolvería llamando a realloc De esto se encarga FPC. Si SetLength no falla, esta garantizado que la memoria reservada para el array es un segmento continuo de memoria. Internamente FPC se encarga de que todos los detalles para que esto sea así. No por nada se les llama Arrays Dinámicos :). pero en la documentación no entiendo eso. yo entiendo que se debe llamar _una vez_ a SetLength con un valor mayor a cero y otra vez con valor igual a cero si se desea borrar los datos del array. http://www.freepascal.org/docs-html/rtl/system/setlength.html He leído el artículo enlazado y la lectura que hago no me dice nada a cerca de que se *deba* usa solo una vez, y si no lo dice es por que no es así, puedes usar SetLength las veces que sea necesario. Y si en algún punto quieres tener la conciencia tranquila con respecto a la memoria reservada dinámicamente puedes especificar 0 como número de elementos y eso "limpiara" el array, aquí cleared se usa para indicar que la memoria usada por el array será liberada. Lo que no dice es que aumentar el número de elementos del array no "elimina" los elementos existentes, sino que solo hace más espacio para la cantidad extra deseada de elementos. De nuevo internamente FPC hace todo lo necesario para que al final todos los elementos del array estén dentro de un segmento continuo de memoria. ¿qué opinan uds? Saludos. Jesus Reyes A. <http://www.opera.com/mail/> _______________________________________________ Lazarus-es mailing list Lazarus-es en lists.lazarus-ide.org http://lists.lazarus-ide.org/listinfo/lazarus-es

------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160720/03fa2a23/attachment.html>

Reply by email

Rafael Bidegain
to Jesus Reyes A.: En Tue, 19 Jul 2016 23:14:23 -0500, Rafael Bidegain <r.bidegain en gmail.com> Y así es,…
Jesus Reyes A. wrote 42 lines
En Tue, 19 Jul 2016 23:14:23 -0500, Rafael Bidegain <r.bidegain en gmail.com> escribió: A propósito del tema planteado por Juan M. Puertas y el aporte realizado por Jesus Reyes A. Me ha llamado la atención el uso de la función SetLength en la función vbSplit. function vbSplit(S: string; Delimiter: char): TStrArray; var C: integer; begin repeat SetLength(Result, Length(Result) + 1); C := Pos(Delimiter, S); if C = 0 then C := Length(S) + 1; Result[Length(Result) - 1] := Copy(S, 1, C - 1); Delete(S, 1, C); until Length(S) = 0; end; Yo creo que en esa función el programador asumió que SetLength siempre expandirá el array. Y así es, de lo contrario debería arrojar un error que en este caso particular no es manejado. Según mis pocos conocimientos para que eso sea posible, en tiempo de compilación, se debería reservar una cantidad importante de memoria contigua para el posible crecimiento de cada array dinamico que el programador declare o implementar en SetLength una opción para mover el array a otra zona si no hay espacio disponible. en C se resolvería llamando a realloc De esto se encarga FPC. Si SetLength no falla, esta garantizado que la memoria reservada para el array es un segmento continuo de memoria. Internamente FPC se encarga de que todos los detalles para que esto sea así. No por nada se les llama Arrays Dinámicos :).

Está claro que eso es algo que resuelve Free Pascal Compiler! por otra parte, los array siempre son bloques de memoria contigua. Lo que de alguna manera me llama la atención es que si cada función tiene su pila (no sé si realmente es así, creo que hace muchos años era así) y ese array está en la pila de la función esta en algún momento se podría terminar y SetLength debería devolver error.

Si el array dinámico de la función no se crea en la pila de la función sino en el lugar de las variables públicas, el problema quizás sea menor, pero de todas maneras se debería comprobar si se pudo expandir el array.

Show quoted text 11 lines
pero en la documentación no entiendo eso. yo entiendo que se debe llamar _una vez_ a SetLength con un valor mayor a cero y otra vez con valor igual a cero si se desea borrar los datos del array. http://www.freepascal.org/docs-html/rtl/system/setlength.html He leído el artículo enlazado y la lectura que hago no me dice nada a cerca de que se *deba* usa solo una vez, y si no lo dice es por que no es así, puedes usar SetLength las veces que sea necesario.

Es cierto no lo dice, lo interpreté del ejemplo

Show quoted text 5 lines
Y si en algún punto quieres tener la conciencia tranquila con respecto a la memoria reservada dinámicamente puedes especificar 0 como número de elementos y eso "limpiara" el array, aquí cleared se usa para indicar que la memoria usada por el array será liberada.

Esto me hace ruido,
estoy pensando en que puedo liberar la memoria y después usar los datos de esa zona de memoria que fué liberada.

Lo que no dice es que aumentar el número de elementos del array no "elimina" los elementos existentes, sino que solo hace más espacio para la cantidad extra deseada de elementos.

Quizás sea buena idea solicitar que se incluya en la documentación de SetLength que pasa con los datos<

De nuevo internamente FPC hace todo lo necesario para que al final todos los elementos del array estén dentro de un segmento continuo de memoria.

si, de nuevo. de eso se tratan los array, son espacios contiguos de memoria, por eso se los puede acceder con un índice.

Show quoted text 15 lines
¿qué opinan uds? Saludos. Jesus Reyes A. <http://www.opera.com/mail/> _______________________________________________ Lazarus-es mailing list Lazarus-es en lists.lazarus-ide.org http://lists.lazarus-ide.org/listinfo/lazarus-es
Rafael Bidegain Ya que los cuerdos no hablan, hablará el loco. (The Fool, Padraic Pearse) # yo quiero educación libre. ¡YA! ------------ próxima parte ------------ Se ha borrado un adjunto en formato HTML... URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160720/085d7c51/attachment-0001.html>

Reply by email

Jesus Reyes A.
to Rafael Bidegain
Show quoted text 10 lines
por otra parte, los array siempre son bloques de memoria contigua.Lo que de alguna manera me llama la atención es que si cada función tiene su pila (no sé si >realmente es así, creo que hace muchos años era así) y ese array está en la pila de la función esta >en algún momento se podría terminar y SetLength debería devolver error. Si el array dinámico de la función no se crea en la pila de la función sino en el lugar de las >variables públicas, el problema quizás sea menor, pero de todas maneras se debería comprobar si se >pudo expandir el array.

Es que "pila" puede ser un término confuso pues al parecer "apilar" se puede traducir tanto como stack pero también como heap. Pero bueno, si estoy en lo correcto y según tus comentarios, entonces me parece que con "pila" te refieres al stack de la función y no al heap. No, no esta en el stack (Perdón por el cambio de palabras pero me parece que es un poco mas claro así), el resultado de la función por ser un array dinámico se comporta como una referencia.

Show quoted text 7 lines
> Y si en algún punto quieres tener la conciencia tranquila con respecto > a la memoria reservada >>dinámicamente puedes especificar 0 como número > de elementos y eso "limpiara" el array, aquí >>cleared se usa para > indicar que la memoria usada por el array será liberada. Esto me hace ruido,estoy pensando en que puedo liberar la memoria y después usar los datos de esa zona de memoria que >fué liberada.

Claro, lo mismo pasa con cualquier otra zona de memoria liberada dinámicamente, si sabes cual era la dirección de memoria puedes acceder a ella. Eso no significa que sea algo seguro de hacer, ahí ya no hay garantías, el contenido anterior pudo ya haber sido sobre escrito con algo mas.

Show quoted text 7 lines
> >>> Lo que no dice es que aumentar el número de elementos del array no >>> "elimina" los elementos >>existentes, sino que solo hace más espacio >>> para la cantidad extra deseada de elementos. Quizás sea buena idea solicitar que se incluya en la documentación de SetLength que pasa con los >datos<

Bueno, en la documentación de SetLength no esta toda la información, pero si buscamos en la información referente a los arrays dinámicos la cosa cambia. Lo que no es mala idea es que se incluya en la documentación de SetLength un enalce hacia la documentación de los arrays dinámicos.

Éste artículo del wiki me parece informativo:
http://wiki.freepascal.org/Dynamic_array necesitamos una versión en Español! :)

Jesus Reyes A.
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160720/da59285b/attachment.html>

Reply by email

Juan M. Puertas
to Jesus Reyes A.

Según el artículo de la Wiki, cuando se sale del procedimiento o función en el que se encuentra SetLength, la memoria se libera automáticamente. Saludos :-)

Jesus Reyes A. wrote 64 lines
por otra parte, los array siempre son bloques de memoria contigua. Lo que de alguna manera me llama la atención es que si cada función tiene su pila (no sé si realmente es así, creo que hace muchos años era así) y ese array está en la pila de la función esta en algún momento se podría terminar y SetLength debería devolver error. Si el array dinámico de la función no se crea en la pila de la función sino en el lugar de las variables públicas, el problema quizás sea menor, pero de todas maneras se debería comprobar si se pudo expandir el array. Es que "pila" puede ser un término confuso pues al parecer "apilar" se puede traducir tanto como stack pero también como heap. Pero bueno, si estoy en lo correcto y según tus comentarios, entonces me parece que con "pila" te refieres al stack de la función y no al heap. No, no esta en el stack (Perdón por el cambio de palabras pero me parece que es un poco mas claro así), el resultado de la función por ser un array dinámico se comporta como una referencia. > Y si en algún punto quieres tener la conciencia tranquila con respecto a > la memoria reservada dinámicamente puedes especificar 0 como número de > elementos y eso "limpiara" el array, aquí cleared se usa para indicar que > la memoria usada por el array será liberada. > Esto me hace ruido, estoy pensando en que puedo liberar la memoria y después usar los datos de esa zona de memoria que fué liberada. Claro, lo mismo pasa con cualquier otra zona de memoria liberada dinámicamente, si sabes cual era la dirección de memoria puedes acceder a ella. Eso no significa que sea algo seguro de hacer, ahí ya no hay garantías, el contenido anterior pudo ya haber sido sobre escrito con algo mas. > Lo que no dice es que aumentar el número de elementos del array no > "elimina" los elementos existentes, sino que solo hace más espacio para la > cantidad extra deseada de elementos. > Quizás sea buena idea solicitar que se incluya en la documentación de SetLength que pasa con los datos< Bueno, en la documentación de SetLength no esta toda la información, pero si buscamos en la información referente a los arrays dinámicos la cosa cambia. Lo que no es mala idea es que se incluya en la documentación de SetLength un enalce hacia la documentación de los arrays dinámicos. Éste artículo del wiki me parece informativo: http://wiki.freepascal.org/Dynamic_array necesitamos una versión en Español! :) Jesus Reyes A. _______________________________________________ Lazarus-es mailing list Lazarus-es en lists.lazarus-ide.org http://lists.lazarus-ide.org/listinfo/lazarus-es

------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160720/43616c1f/attachment.html>

Reply by email

Jesus Reyes A.
to Juan M. Puertas

En Wed, 20 Jul 2016 11:28:35 -0500, Juan M. Puertas

<soft.sirius en gmail.com> wrote
Según el artículo de la Wiki, cuando se sale del procedimiento o función en el que se encuentra SetLength, la memoria >se libera automáticamente. Saludos :-)

Esto es así para las variables declaradas dentro de las funciones o procedimientos, en el caso que nos ocupa hoy, estamos hablando de un resultado de tipo array dinámico, "Result" en éste caso no es una variable común y corriente.

De hecho hace poco, a finales de junio pasado, ha tenido lugar una conversación que resulta esclarecedora, una persona pregunta: ¿Qué Tipos necesitamos inicializar a null/nil/zero/'' cuando son el resultado de una función? un desarrollador de FPC responde: "Los resultados de todos los Tipos (auto manipulados o no) necesitan ser ajustados a 'vacio' si quieres regresarlos como un resultado 'vacio'" y mas adelante en la conversación: "Como regla general, los resultados de una función no contienen un valor predecible al entrar en la función."

Esto aplica directamente en el caso que nos ocupa pues en la función vbSplit el resultado de la función en ningún momento es inicializado y por lo que acabamos de leer, el resultado contiene un valor indefinido. He aquí la función en cuestión:

  1 function vbSplit(S: string; Delimiter: char): TStrArray;
  2 var
  3   C: integer;
  4 begin
  5   repeat
  6     SetLength(Result, Length(Result) + 1);
  7     C := Pos(Delimiter, S);
  8     if C = 0 then
  9       C := Length(S) + 1;
10     Result[Length(Result) - 1] := Copy(S, 1, C - 1);
11     Delete(S, 1, C);
12   until Length(S) = 0;
13 end;

Según lo anterior, la línea 6 Length(Result) es indefinido (para todo propósito "indefinido" aquí se refiere a un detalle interno que depende de la implementación actual en el compilador). En mi opinión SetLength se esta utilizando correctamente solo que antes que nada el resultado debe ser inicializado y para ello basta insertar entre las lineas 5 y 6 un SetLength(Result, 0); y listo.

Ya de paso y encarrerado me atrevo a sugerir algo, la unidad StrUtils proporcionada por la RTL de FPC contiene muchas funciones entre ellas esta ExtractWord que tiene la siguiente declaración:

function ExtractWord(N: Integer; const S: string; const WordDelims:
TSysCharSet): string;
Es muy fácil su uso, en este caso ComboPais.Items.Add(ExtractWord(1,
sLinea, ['/']));

Y digo de paso por que vbSplit corregida no tiene absolutamente ningún problema :)

Saludos.

Jesus Reyes A.
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160720/11a69abf/attachment-0001.html>

Reply by email

Jesus Reyes A.
to Jesus Reyes A.

En Wed, 20 Jul 2016 14:02:05 -0500, Jesus Reyes A. <jesusrmx en gmail.com>

Show quoted text 20 lines
1 function vbSplit(S: string; Delimiter: char): TStrArray; 2 var 3 C: integer; 4 begin 5 repeat 6 SetLength(Result, Length(Result) + 1); 7 C := Pos(Delimiter, S); 8 if C = 0 then 9 C := Length(S) + 1; 10 Result[Length(Result) - 1] := Copy(S, 1, C - 1); 11 Delete(S, 1, C); 12 until Length(S) = 0; 13 end; Según lo anterior, la línea 6 Length(Result) es indefinido (para todo propósito "indefinido" aquí se >refiere a un detalle interno que depende de la implementación actual en el compilador). En mi opinión >SetLength se esta utilizando correctamente solo que antes que nada el resultado debe ser inicializado >y para ello basta insertar entre las lineas 5 y 6 un SetLength(Result, 0); y listo.

Perdón, obviamente me he equivocado, no es entre las líneas 5 y 6 sino entre las líneas 4 y 5.

Jesus Reyes A.
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160720/514d3e11/attachment.html>

Reply by email

Rafael Bidegain
to Jesus Reyes A.: En Wed, 20 Jul 2016 11:28:35 -0500, Juan M. Puertas Esto es así para las variables…
function ExtractWord(N: Integer; const S: string; const WordDelims:
TSysCharSet): string;
Show quoted text 17 lines
Es muy fácil su uso, en este caso ComboPais.Items.Add(ExtractWord(1, sLinea, ['/'])); Y digo de paso por que vbSplit corregida no tiene absolutamente ningún problema :) Saludos. Jesus Reyes A. _______________________________________________ Lazarus-es mailing list Lazarus-es en lists.lazarus-ide.org http://lists.lazarus-ide.org/listinfo/lazarus-es Jesús, muchas gracias esclarecer el tema.

me gustó mucho el comentario del mes pasado sobre la inicialización de las variables.

Aun después de tu fix, a la función vbSplit esta sigue sin gustarme. yo la implementaría con una sola llamada a SetLength.
previo llamado a WordCount y usaría tu recomendación ExtractWord.

quizás el autor en algún momento modificó esa función y el uso de TokenizerClass tuvo que ver con eso.

Rafael Bidegain Ya que los cuerdos no hablan, hablará el loco. (The Fool, Padraic Pearse) # yo quiero educación libre. ¡YA! ------------ próxima parte ------------ Se ha borrado un adjunto en formato HTML... URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160720/f6484118/attachment.html>

Reply by email

Juan M. Puertas
to Rafael Bidegain

Muchas gracias amigos.
He seguido vuestros consejos. :-)

Rafael Bidegain wrote 46 lines
function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string; > > Es muy fácil su uso, en este caso ComboPais.Items.Add(ExtractWord(1, > sLinea, ['/'])); > > Y digo de paso por que vbSplit corregida no tiene absolutamente ningún > problema :) > > Saludos. > > Jesus Reyes A. > > _______________________________________________ > Lazarus-es mailing list > Lazarus-es en lists.lazarus-ide.org > http://lists.lazarus-ide.org/listinfo/lazarus-es > > Jesús, muchas gracias esclarecer el tema. me gustó mucho el comentario del mes pasado sobre la inicialización de las variables. Aun después de tu fix, a la función vbSplit esta sigue sin gustarme. yo la implementaría con una sola llamada a SetLength. previo llamado a WordCount y usaría tu recomendación ExtractWord. quizás el autor en algún momento modificó esa función y el uso de TokenizerClass tuvo que ver con eso. -- Rafael Bidegain Ya que los cuerdos no hablan, hablará el loco. (The Fool, Padraic Pearse) # yo quiero educación libre. ¡YA! _______________________________________________ Lazarus-es mailing list Lazarus-es en lists.lazarus-ide.org http://lists.lazarus-ide.org/listinfo/lazarus-es

------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160720/0c4a0dcf/attachment.html>

Reply by email

Rafael Bidegain
to Jesus Reyes A.: En Wed, 20 Jul 2016 11:28:35 -0500, Juan M. Puertas Esto es así para las variables…
Jesus Reyes A. wrote
Y digo de paso por que vbSplit corregida no tiene absolutamente ningún problema :) Perdón que insista con este tema.
hice un prueba con una función que devuelve un array dinámico y luego llamé
a getheapstatus();
mi_heap := getheapstatus();
writeln('TotalAddrSpace..: ', mi_heap.TotalAddrSpace);
writeln('TotalAllocated..: ', mi_heap.TotalAllocated);
writeln('TotalFree.......: ', mi_heap.TotalFree);

Pude notar que con cada llamada a la función (similar a vbSplit) TotalAllocated aumentaba y TotalFree disminuía.

No encontré la forma de revertir eso

en mi opinión, y hasta que no encuentre la forma de liberar la memoria vbSplit tiene un problema serio.

saludos

Rafael Bidegain Ya que los cuerdos no hablan, hablará el loco. (The Fool, Padraic Pearse) # yo quiero educación libre. ¡YA! ------------ próxima parte ------------ Se ha borrado un adjunto en formato HTML... URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160725/4dbd8f53/attachment.html>

Reply by email

Jesus Reyes A.
to Rafael Bidegain

En Mon, 25 Jul 2016 15:39:27 -0500, Rafael Bidegain <r.bidegain en gmail.com>

Show quoted text 25 lines
El 20 de julio de 2016, 16:02, Jesus Reyes A. <jesusrmx en gmail.com> escribió: > Y digo de paso por que vbSplit corregida no tiene absolutamente ningún > problema :) > Perdón que insista con este tema. hice un prueba con una función que devuelve un array dinámico y luego llamé a getheapstatus(); mi_heap := getheapstatus(); writeln('TotalAddrSpace..: ', mi_heap.TotalAddrSpace); writeln('TotalAllocated..: ', mi_heap.TotalAllocated); writeln('TotalFree.......: ', mi_heap.TotalFree); Pude notar que con cada llamada a la función (similar a vbSplit) TotalAllocated aumentaba >y TotalFree disminuía. No encontré la forma de revertir eso en mi opinión, y hasta que no encuentre la forma de liberar la memoria vbSplit tiene un problema >serio. saludos --Rafael Bidegain

Podrías por favor compartir tu programa de prueba?.

Jesus Reyes A.
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160725/dc5563ae/attachment.html>

Reply by email

Rafael Bidegain
to Jesus Reyes A.
Podrías por favor compartir tu programa de prueba?.

si.
es este:

program ad1;
type
TAD = array of string;
function hacer_TAD(a,b,c:string) : TAD;
begin
SetLength(Result,3);
Result[0] := a;
Result[1] := b;
Result[2] := c;
end;
procedure mostar_heap();
var
mi_heap : THeapStatus;
begin
mi_heap := getheapstatus();
writeln('TotalAddrSpace..: ', mi_heap.TotalAddrSpace);
//writeln('TotalUncommitted: ', mi_heap.TotalUncommitted);
//writeln('TotalCommitted..: ', mi_heap.TotalCommitted);
writeln('TotalAllocated..: ', mi_heap.TotalAllocated);
writeln('TotalFree.......: ', mi_heap.TotalFree);
//writeln('FreeSmall.......: ', mi_heap.FreeSmall);
//writeln('FreeBig.........: ', mi_heap.FreeBig);
//writeln('Unused..........: ', mi_heap.Unused);
//writeln('Overhead........: ', mi_heap.Overhead);
writeln('HeapErrorCode...: ', mi_heap.HeapErrorCode);
writeln('-------------------------------------');
end;
(*
compilar de esta forma:
fpc -MObjfpc ad1.pas

si no se compila con el modo Objfpc o delphi da error por el uso de Result

*)

var
v1,v2,v3,v4 : TAD;
pila : THeapStatus;
begin
mostar_heap();
SetLength(v1,5);
mostar_heap();
v1[0] := 'Aaaaaaaaa';
v1[1] := 'Bbbbbb';
v1[2] := 'Cccccccc';
v1[3] := 'Dddddddd';
v1[4] := 'Eeeeeee';
v2 := hacer_TAD('11111111','222222','33333');
mostar_heap();
v3 := hacer_TAD('----------','=====','#######');
mostar_heap();
v4 := TAD.create('uno','dos','tres','cuatro','cinco','seis','siete');
mostar_heap();
SetLength(v4,0);
mostar_heap();
writeln(v1[0]);
writeln(v1[4]);
writeln('=========================================');
writeln(v2[0]);
writeln(v2[1]);
writeln(v2[2]);
writeln('=========================================');
writeln(v3[0]);
writeln(v3[1]);
writeln(v3[2]);
writeln('=========================================');
mostar_heap();
//las siguientes lineas son las que producen el error:
//Runtime error 216 at $000000000041CE1B
//  $000000000041CE1B
//  $000000000040018F
// esto es por la llamada a SetLength en la línea 62
writeln(v4[0]);
writeln(v4[3]);
writeln(v4[6]);
end.
Rafael Bidegain Ya que los cuerdos no hablan, hablará el loco. (The Fool, Padraic Pearse) # yo quiero educación libre. ¡YA! ------------ próxima parte ------------ Se ha borrado un adjunto en formato HTML... URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160725/a0a599ed/attachment.html>

Reply by email

Jesus Reyes A.
to Rafael Bidegain

De hecho, no estoy familiarizado con las interioridades del administrador de memoria predeterminado de FPC por lo que me llama la atención como en los dos primeros logs al compararlos, el valor de TotalFree después del primer SetLength en lugar de disminuir aumenta, TotalAllocated me parece que consistentemente aumenta después del primer SetLength. Lo que he notado en tu test, es que la memoria no regresa al sistema sino hasta que termina el programa, y esto es lógico pues las variables que mantienen la memoria reservada son locales al procedimiento principal. Esto es fácilmente comprobable. Simplemente activa la funcionalidad Heaptrc en la opciones del proyecto y comprobaras que al final el programa no presenta bloques sin liberar.

Yo creo que una mejor manera de comprobar si la memoria es o no liberada de los arrays dinámicos es poner todo el código del procedimiento principal en una subrutina, algo así como:

<pre>
begin
   WriteLn('Inicial');
   mostar_heap();
   HacerTests;
   WriteLn('ElFinal');
   mostar_heap();
end.
</pre>

HacerTests es exactamente lo mismo que hacia antes el procedimiento principal.

Acá, TotalAllocated antes y después muestra lo mismo. Yo creo (y nunca mejor dicho :)) que el administrador de memoria de FPC mantiene estructuras o bloques reservados que luego son liberados en algún tipo de cache, de manera que no me parece extraño que la memoria que aparentemente es reservada y luego liberada no se corresponda exactamente con los valores antes y después.

Jesus Reyes A.

En Mon, 25 Jul 2016 20:45:17 -0500, Rafael Bidegain <r.bidegain en gmail.com>

Show quoted text 8 lines
> >>> Podrías por favor compartir tu programa de prueba?. si. es este: program ad1; .... end.

------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus-es/attachments/20160726/077b9136/attachment.html>

Reply by email