Bennu Game Development

Foros en Español => Mesa de Ayuda => Mensaje iniciado por: Arcontus en Enero 19, 2018, 12:26:54 pm

Título: Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: Arcontus en Enero 19, 2018, 12:26:54 pm
Hola chicos,

El caso es que he tenido una serie de errores "string alloc: out of memory" en mi proyecto, he leido varios temas al respecto de utilizar punteros con strings y no me queda claro si los estoy utilizando correctamente.

Para comenzar, algunos procesos tenían declaradas arrays de strings (string str[4]), esto lo he cambiado a strings únicas (str1, str2, ...). Entiendo que esto estaba mal, ¿correcto? y diría sin estar aun seguro al 100% que esto ha solucionado el problema del "string alloc: out of memory" en mi proyecto.

Por otro lado utilizo una serie de funciones para trabajar con cadenas de texto y querría descartar con vuestra ayuda que estuviera implementando el uso de punteros de string de manera incorrecta.

La idea es tener un proceso "A" con 2 strings A1 y A2, ¿puede llamar "A" a una funcion pasando los punteros de ambas strings (&A1, &A2) para que se modifique una de ellas dentro de esa funcion?

Os cuelgo una de mis funciones como ejemplo:

Código: [Seleccionar]
FUNCTION split_string(string * mensaje, string *str_valor, int seccion) //Dado una cadena mensaje con "cadena1|cadena2" devuelve el string apropiado sobre str_valor segun seccion proporcionada.
PRIVATE
    int indice, inicio, marca, tam;
END
BEGIN
    tam = len((*mensaje));
    if (tam > 0)
        marca = find((*mensaje),"|");
        if (marca > -1)
            if (seccion== 0)
                (*str_valor) = substr((*mensaje),0,marca);
            else
                (*str_valor) = substr((*mensaje),marca+1, tam);
            END
        END
    END
END

Gracias de antemano,
Un saludo!
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 19, 2018, 02:13:41 pm
las strings no pueden usarse con punteros, son objetos que tienen un contador de uso, y si es un puntero, no se sabe si el puntero apunta a un identificador de string o a un area con basura o sin alocar.

(revisare nuevamente el sistema a ver si puedo implementar algo al respecto... aunque creo que no es seguro...)
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: Arcontus en Enero 19, 2018, 03:08:44 pm
Hola Splinter, no acabo de entender lo que comentas de que no pueden usarse, al menos la funcion "write_string" si usa el puntero para algo y entiendo que no da problemas.
Te agradecería enormemente que me dieras más detalle de como funciona string y porque a veces apunta a basura y el mecanismo que usa write_string para no petar.

Gracias!
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 19, 2018, 08:13:12 pm
el tema es, las string son en realidad un numero entero representa el indice dentro de una tabla de strings, y donde ademas hay un contador de usos... y cuando este contador de usos es 0, la string se libera (es un garbage collector), en el caso de los punteros, el motor no puede saber si *puntero_a_string, esta apuntando a una string o todavia no fue asignado a nada, entonces el motor no actualiza el contador de usos ahi...

cuando tu haces un &var_string, lo que haces es apuntar a la direccion de la variable que contiene el id (indice) de la string real, esta direccion no cambia nunca... y esta apuntando realmente a una string real, con un espacio previamente reservado por el motor y con un contador de usos controlado.
ahora cuando tu pasas libremente punteros a string, estos inicialmente no apuntan a un area estatica, apuntan a lo que aloques, a menos que tu puntero sea un puntero a una variable ya declarada como string... pero como sea, el motor no controla el contador de usos con punteros, porque no sabe que realmente esta usado y que no... por ende, puede ocurrir que cuando tu puntero quiera acceder a la string, el puntero realmente este apuntando a una string que ya no existe, puesto que se elimino por el contador de usos.

por eso, a menos que sepas que estas haciendo, no es recomendable usar punteros a string.

es dificil de explicar, asi que puede que tambien sea dificil de entender...
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 19, 2018, 08:27:04 pm
agrego, o puede que este apuntando a otra area de memoria diferente... por ejemplo, si usas realloc...

cuando se sale de una funcion, toda string que su contador de uso sea igual a 0, es eliminada.
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: Arcontus en Enero 19, 2018, 09:13:51 pm
agrego, o puede que este apuntando a otra area de memoria diferente... por ejemplo, si usas realloc...

cuando se sale de una funcion, toda string que su contador de uso sea igual a 0, es eliminada.

Entiendo que eso que comentas también sucede con los write_strings, de hecho con cualquier write_*, si el proceso que creo la variable referenciada por write_* muere, o se hace un delete_text() o petada al canto (como es normal).

En mi caso uso esos punteros de la siguiente manera:

Código: [Seleccionar]
FUNCTION split_string(string * mensaje, string *str_valor, int seccion) //Dado una cadena mensaje con "cadena1|cadena2" devuelve el string apropiado sobre str_valor segun seccion proporcionada.
PRIVATE
    int indice, inicio, marca, tam;
END
BEGIN
    tam = len((*mensaje));
    if (tam > 0)
        marca = find((*mensaje),"|");
        if (marca > -1)
            if (seccion== 0)
                (*str_valor) = substr((*mensaje),0,marca);
            else
                (*str_valor) = substr((*mensaje),marca+1, tam);
            END
        END
    END
END

PROCESS a()
PRIVATE
    string mistring1 = "Hola|Adios", mistring2;
    int estado;
END
BEGIN
    split_string(&mistring1, &mistring2, estado);
    write_string(0,200,200,0,&mistring2);
    LOOP
        FRAME;
        if (key(_space))
            while(key(_space))
                FRAME;
            END
            if (estado == 0)
                estado = 1;
            else
                estado = 0;
            END
            split_string(&mistring1, &mistring2, estado);
        END
        FRAME;
    END
END


Proces A() crea 2 strings mistring1y mistring2 en su seccion private, y llama a la funcion  split_string() para obtener una de las secciones previamente asignadas.
Si he entendido correctamente, esto que pretendo es un uso correcto de los punteros de string, por que no se utiliza realloc ni malloc ni nada por el estilo para crearlos.

¿SplinterGU code approved?
 ;D ;D

Gracias por vuestra ayuda,
Un saludo!
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: Drumpi en Enero 20, 2018, 01:31:13 am
Yo en su día tuve millones de problemas con los array de strings.
No conocía exactamente el funcionamiento interno de las strings, suponía que eran un array de memoria dinámica que se agrandaba y encogía en función del número de caracteres, y que por la alineación de memoria de los propios array, provocaba que los espacios de memoria se empezaran a pisar unos a otros.

Así que me definí un tipo "string_node" tal como:
Código: [Seleccionar]
type string_node
    string cadena;
    string_node pointer sig
end
Y luego me creé la tipica lista enlazada de nodos, con funciones para añadir, eliminar nodos, buscar, recorrer, vaciar, etc, y la llamé "string_class". Sí, básicamente emulaba la clase String de Java que estaba estudiando en aquel momento.
Se resolvieron TODOS los problemas. Splinter insiste que eso debería fallar en algún momento, pero debe andar ya por los 7 años sin excepciones de ningún tipo.

El código lo subí al foro. http://forum.bennugd.org/index.php/topic,2208
Creo que tuve que arreglar un par de cosillas desde entonces, pero más fallos míos que "malas prácticas" :D
Mi principal uso: crear un fichero de texto con frases y cargarlas todas en memoria, ideal para almacenar diálogos o los textos en el idioma que se elija para el programa.
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 20, 2018, 07:34:47 am
agrego, o puede que este apuntando a otra area de memoria diferente... por ejemplo, si usas realloc...

cuando se sale de una funcion, toda string que su contador de uso sea igual a 0, es eliminada.

Entiendo que eso que comentas también sucede con los write_strings, de hecho con cualquier write_*, si el proceso que creo la variable referenciada por write_* muere, o se hace un delete_text() o petada al canto (como es normal).

En mi caso uso esos punteros de la siguiente manera:

Código: [Seleccionar]
FUNCTION split_string(string * mensaje, string *str_valor, int seccion) //Dado una cadena mensaje con "cadena1|cadena2" devuelve el string apropiado sobre str_valor segun seccion proporcionada.
PRIVATE
    int indice, inicio, marca, tam;
END
BEGIN
    tam = len((*mensaje));
    if (tam > 0)
        marca = find((*mensaje),"|");
        if (marca > -1)
            if (seccion== 0)
                (*str_valor) = substr((*mensaje),0,marca);
            else
                (*str_valor) = substr((*mensaje),marca+1, tam);
            END
        END
    END
END

PROCESS a()
PRIVATE
    string mistring1 = "Hola|Adios", mistring2;
    int estado;
END
BEGIN
    split_string(&mistring1, &mistring2, estado);
    write_string(0,200,200,0,&mistring2);
    LOOP
        FRAME;
        if (key(_space))
            while(key(_space))
                FRAME;
            END
            if (estado == 0)
                estado = 1;
            else
                estado = 0;
            END
            split_string(&mistring1, &mistring2, estado);
        END
        FRAME;
    END
END


Proces A() crea 2 strings mistring1y mistring2 en su seccion private, y llama a la funcion  split_string() para obtener una de las secciones previamente asignadas.
Si he entendido correctamente, esto que pretendo es un uso correcto de los punteros de string, por que no se utiliza realloc ni malloc ni nada por el estilo para crearlos.

¿SplinterGU code approved?
 ;D ;D

Gracias por vuestra ayuda,
Un saludo!

me parece que no es correcto, mañana lo reviso bien, reviso el codigo y te respondo...
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 20, 2018, 07:37:03 am
Yo en su día tuve millones de problemas con los array de strings.
No conocía exactamente el funcionamiento interno de las strings, suponía que eran un array de memoria dinámica que se agrandaba y encogía en función del número de caracteres, y que por la alineación de memoria de los propios array, provocaba que los espacios de memoria se empezaran a pisar unos a otros.

Así que me definí un tipo "string_node" tal como:
Código: [Seleccionar]
type string_node
    string cadena;
    string_node pointer sig
end
Y luego me creé la tipica lista enlazada de nodos, con funciones para añadir, eliminar nodos, buscar, recorrer, vaciar, etc, y la llamé "string_class". Sí, básicamente emulaba la clase String de Java que estaba estudiando en aquel momento.
Se resolvieron TODOS los problemas. Splinter insiste que eso debería fallar en algún momento, pero debe andar ya por los 7 años sin excepciones de ningún tipo.

El código lo subí al foro. http://forum.bennugd.org/index.php/topic,2208
Creo que tuve que arreglar un par de cosillas desde entonces, pero más fallos míos que "malas prácticas" :D
Mi principal uso: crear un fichero de texto con frases y cargarlas todas en memoria, ideal para almacenar diálogos o los textos en el idioma que se elija para el programa.

drumpi, ahi no estas usando punteros a strings... igual creo que tampoco es correcto, aunque depende de otras cosas...

el punto esta en el contador de usos de las strings... si llegan a 0, se eliminan de la memoria...
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: Arcontus en Enero 20, 2018, 09:21:59 am
SplinterGU como siempre tiene razón, la función "split_string" que he escrito es inestable. La mayoría del tiempo funciona como es debido pero no el 100% del tiempo, lo que provoca que se cierre el proyecto de manera inesperada, a veces si, otras no.

Ahora me gustaría saber:
A: Que es lo que está mal de la función. Así aprendemos todos...
B: Cual es la manera correcta de dado 1 string con "cadena1|cadena2" obtener en otra string el valor de la sección correspondiente.
C: ¿Se podría implementar algo como "exists_string()" para acceder con seguridad a la zona de memoria u otro tipo de mecanismo fiable?

Gracias de antemano,
Un saludo!
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 20, 2018, 06:29:34 pm
podes usar arrays de bytes o char (no recuerdo cual de los 2)

byte * (o char *, probalo), eso es seguro, siempre y cuando hagas el alloc pertinente.

Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 21, 2018, 12:04:46 am
he estado analizando el codigo, debuguando y probando... y no, no tenia razon...

veo que si esta soportado punteros a strings de forma correcta.

o lo corregi en algun momento, o algo paso, en verdad no recuerdo haberlo corregido, pero veo que funciona correcto.

si esto no funciona es porque hay algun bug en algun lugar del motor...

pero tu funcion es correcta... y debugueandola a nivel C, esta todo bien el uso de strings.

aunque no necesitas pasar el primer parametro como puntero, puedes pasarlo como string tranquilamente.

igual tengo que probar completamente el sistema, quizas en algun caso especifico falla, pero con retornos por puntero va muy bien.
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: Arcontus en Enero 21, 2018, 11:30:29 am
Hasta mañana no podre hacer mas pruebas, ya que hoy no dispongo de ordenador, pero en los debugs que hice del programa, en un caso se cerro subitamente dentro de la funcion split_string() al asignar un valor a uno de los punteros.
En otro caso fue justo la siguiente instruccion, desde el proceso que invoca a split_string() al asignar un nuevo valor a la string que le paso a split_string().

No puedo descartar que sea otra cosa la que esta afectando, aun que me he revisado el codigo un monton de veces. De momento la unica pista que tengo es un pete de string alloc:out of memory y el registro de la ultima instruccion que se ejecuto en modo debug antes de petar el programa.

La verdad es que estoy tremendamente ofuscado con este problema.

Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 21, 2018, 11:57:03 am
igualmente, tras dar muchas vueltas abrazado a mi almohada y entre soñar y pensar en los datos que recolecte de las pruebas de hace unas horas, parece que efectivamente hay al menos un problema con las strings, que explicare cuando lo tenga bien confirmado, y creo que ahi se fundamenta lo que dije anteriormente... sin embargo, tu funcion de string parece funcionar correctamente...

pregunta, estas usando por casualidad punteros a strings creados con alloc (mem_alloc, mem_calloc, etc)?

PD: debo confesar que dormi solo 3 horas, este tema de las strings no me dejo dormir... :P
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: Arcontus en Enero 21, 2018, 04:35:14 pm
igualmente, tras dar muchas vueltas abrazado a mi almohada y entre soñar y pensar en los datos que recolecte de las pruebas de hace unas horas, parece que efectivamente hay al menos un problema con las strings, que explicare cuando lo tenga bien confirmado, y creo que ahi se fundamenta lo que dije anteriormente... sin embargo, tu funcion de string parece funcionar correctamente...

pregunta, estas usando por casualidad punteros a strings creados con alloc (mem_alloc, mem_calloc, etc)?

PD: debo confesar que dormi solo 3 horas, este tema de las strings no me dejo dormir... :P

Si te soy sincero, a mi tampoco me deja dormir tranquilo. El viernes tuve pesadillas con esto, y no es broma  ;D ;D ;D
No, ya he leido que no hay que crear punteros con mem_alloc, etc, la manera que uso para crear los strings es siempre desde la seccion PRIVATE de un proceso.

He cambiado una funcion que efectivamente estaba mal en mi proyecto y tiene numeros de ser la causante de todos estos problemas... Esa funcion no tiene nada que ver con strings, modifica un int *var al finalizarse, pero dicho puntero en algunos casos podría haber dejado de existir y por ello apuntar a una zona de memoria que no tocara, provocando después el fallo en otro lado del programa..., como no estoy seguro al 100% de haber hallado con el problema continuo investigando.

Gracias por las respuestas,
Un saludo!
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 21, 2018, 06:09:11 pm
con malloc puedes hacer cualquier puntero salvo los de strings... si usas punteros a string que alocas con malloc, los puedes usar, pero nunca se liberan de la memoria, con lo que la cantidad de strings en memoria crecen y crecen y crecen hasta agotar toda la memoria.

estoy intentando ver si le encuentro alguna solucion a esto...
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 24, 2018, 05:32:22 am
tengo una solucion al tema de los punteros a strings, no encontra otra opcion que agregar 3 nuevas funciones, 2 para el tema de allocar una string (que se usa solo para string * que no sean string_pointer = &string) y otra para liberar la string cuando ya no se usa. Y agregue una mas para obtener un puntero directo al buffer de la string en memoria (para poder usarla en un memmove o memcopy a un array de char o bytes, o a disco o lo que sea, aunque esta funcion debe ser usada con cuidado porque permite modificar las strings base)

las tengo hace 2 dias, pero las estuve probando a fondo y pensando a ver si podia evitarlas, pero no es posible evitarlas.
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: Arcontus en Enero 24, 2018, 09:28:16 am
Esto suenga genial!

cuando encuentres un rato molaría que nos ilustraras sobre esas nuevas funciones. :)

Un saludo!
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 24, 2018, 01:38:58 pm
asi sera
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: Drumpi en Enero 25, 2018, 12:23:07 am
Yo en su día tuve millones de problemas con los array de strings.
No conocía exactamente el funcionamiento interno de las strings, suponía que eran un array de memoria dinámica que se agrandaba y encogía en función del número de caracteres, y que por la alineación de memoria de los propios array, provocaba que los espacios de memoria se empezaran a pisar unos a otros.

Así que me definí un tipo "string_node" tal como:
Código: [Seleccionar]
type string_node
    string cadena;
    string_node pointer sig
end
Y luego me creé la tipica lista enlazada de nodos, con funciones para añadir, eliminar nodos, buscar, recorrer, vaciar, etc, y la llamé "string_class". Sí, básicamente emulaba la clase String de Java que estaba estudiando en aquel momento.
Se resolvieron TODOS los problemas. Splinter insiste que eso debería fallar en algún momento, pero debe andar ya por los 7 años sin excepciones de ningún tipo.

El código lo subí al foro. http://forum.bennugd.org/index.php/topic,2208
Creo que tuve que arreglar un par de cosillas desde entonces, pero más fallos míos que "malas prácticas" :D
Mi principal uso: crear un fichero de texto con frases y cargarlas todas en memoria, ideal para almacenar diálogos o los textos en el idioma que se elija para el programa.

drumpi, ahi no estas usando punteros a strings... igual creo que tampoco es correcto, aunque depende de otras cosas...

Ya lo sé, esa era la idea: como no podía tener un array de strings ni usar alloc para crear un array dinámico para almacenarlas, hice lo que se debe hacer: una lista enlazada con variables sencillas. Al ser nodos enlazados por punteros, es el sistema el que se encarga de reservarle memoria, y mover los bloques si es necesario más espacio para alguna de ellos.
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 25, 2018, 03:21:51 am
Yo en su día tuve millones de problemas con los array de strings.
No conocía exactamente el funcionamiento interno de las strings, suponía que eran un array de memoria dinámica que se agrandaba y encogía en función del número de caracteres, y que por la alineación de memoria de los propios array, provocaba que los espacios de memoria se empezaran a pisar unos a otros.

Así que me definí un tipo "string_node" tal como:
Código: [Seleccionar]
type string_node
    string cadena;
    string_node pointer sig
end
Y luego me creé la tipica lista enlazada de nodos, con funciones para añadir, eliminar nodos, buscar, recorrer, vaciar, etc, y la llamé "string_class". Sí, básicamente emulaba la clase String de Java que estaba estudiando en aquel momento.
Se resolvieron TODOS los problemas. Splinter insiste que eso debería fallar en algún momento, pero debe andar ya por los 7 años sin excepciones de ningún tipo.

El código lo subí al foro. http://forum.bennugd.org/index.php/topic,2208
Creo que tuve que arreglar un par de cosillas desde entonces, pero más fallos míos que "malas prácticas" :D
Mi principal uso: crear un fichero de texto con frases y cargarlas todas en memoria, ideal para almacenar diálogos o los textos en el idioma que se elija para el programa.

drumpi, ahi no estas usando punteros a strings... igual creo que tampoco es correcto, aunque depende de otras cosas...

Ya lo sé, esa era la idea: como no podía tener un array de strings ni usar alloc para crear un array dinámico para almacenarlas, hice lo que se debe hacer: una lista enlazada con variables sencillas. Al ser nodos enlazados por punteros, es el sistema el que se encarga de reservarle memoria, y mover los bloques si es necesario más espacio para alguna de ellos.

por favor, pasame un miniprograma de ejemplo usando esa estructura, asi lo pruebo, pero temo que es incorrecto.
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 25, 2018, 04:24:35 am
drumpi, imagino que tenes algo como esto:

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

type string_node
    string cadena;
    string_node pointer sig;
end

global
    string_node * nodes = NULL;
end

function add_node( string s )
private
    string_node pointer n;
begin
    n = calloc(1,sizeof(string_node));
    n.cadena = s;
    n.sig = nodes;
    nodes = n;
end

function a()
private
    s = "lala";
    string_node pointer p, pointer p1;
begin
    say("# inicial [ a() entry ]");
    string_dump();

    s = "*" + s + "*"; // evitamos la cadena estatica
    string_dump();

    say("## agrego primer nodo");

    add_node(s);
    string_dump();

    say("## agrego segundo nodo");
    add_node(s + "_1");
    string_dump();

    say("## agrego tercer nodo");
    add_node(s + "_2");
    string_dump();

    say("#### free");
    p = nodes;
    while ( p )
        nodes = p.sig;
        free( p );
        p = nodes;
    end
    string_dump();

    say( "# a() exit");
end

begin
    a();
    string_dump();
end

vas a ver que hay 1 funcion nueva string_dump(), esta funcion lo que hace es mostrar las strings en uso
por ejemplo, [STRING]    6 [   1] STATIC: {lala}
id [ cantidad de usos ] {string}

actualmente ese codigo produce este resultado:

Citar
# inicial [ a() entry ]
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]    6 [   1] STATIC: {lala}
[STRING]   32 [   1]: {string_struct}
[STRING] ---- Dumping Used=2 End ----
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]   32 [   1]: {string_struct}
[STRING]   34 [   1]: {*lala*}
[STRING] ---- Dumping Used=2 End ----
## agrego primer nodo
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]   32 [   1]: {string_struct}
[STRING]   34 [   2]: {*lala*}
[STRING] ---- Dumping Used=2 End ----
## agrego segundo nodo
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]   32 [   1]: {string_struct}
[STRING]   34 [   2]: {*lala*}
[STRING]   35 [   1]: {*lala*_1}
[STRING] ---- Dumping Used=3 End ----
## agrego tercer nodo
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]   32 [   1]: {string_struct}
[STRING]   34 [   2]: {*lala*}
[STRING]   35 [   1]: {*lala*_1}
[STRING]   36 [   1]: {*lala*_2}
[STRING] ---- Dumping Used=4 End ----
#### free
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]   32 [   1]: {string_struct}
[STRING]   34 [   2]: {*lala*}
[STRING]   35 [   1]: {*lala*_1}
[STRING]   36 [   1]: {*lala*_2}
[STRING] ---- Dumping Used=4 End ----
# a() exit
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]   32 [   1]: {string_struct}
[STRING]   34 [   1]: {*lala*}
[STRING]   35 [   1]: {*lala*_1}
[STRING]   36 [   1]: {*lala*_2}
[STRING] ---- Dumping Used=4 End ----

aca veremos el problema...

cuando a() termina, todas las strings usadas en su codigo deberian tener uso 0, ya que no son retornadas, pero al usar punteros, estas no se liberan... que si prestas atencion si libera 1 uso de "*lala*".

pero en el ultimo dump (en el main) se ven que quedaron strings sin liberar....

el codigo correcto con las nuevas funcionens seria:

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

type string_node
    string * cadena;
    string_node pointer sig;
end

global
    string_node * nodes = NULL;
end

function add_node( string s )
private
    string_node pointer n;
begin
    n = calloc(1,sizeof(string_node));
    n.cadena = string_alloc(s);
    n.sig = nodes;
    nodes = n;
end

function a()
private
    s = "lala";
    string_node pointer p;
begin
    say("# inicial [ a() entry ]");
    string_dump();

    s = "*" + s + "*"; // evitamos la cadena estatica
    string_dump();

    say("## agrego primer nodo");

    add_node(s);
    string_dump();

    say("## agrego segundo nodo");
    add_node(s + "_1");
    string_dump();

    say("## agrego tercer nodo");
    add_node(s + "_2");
    string_dump();

    say("#### free");
    p = nodes;
    while ( p )
        nodes = p.sig;
        string_release(&p.cadena);
        free( p );
        p = nodes;
    end
    string_dump();

    say( "# a() exit");
end

begin
    a();
    string_dump();
end

salida

Citar
# inicial [ a() entry ]
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]    6 [   1] STATIC: {lala}
[STRING]   32 [   1]: {string_struct_new}
[STRING] ---- Dumping Used=2 End ----
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]   32 [   1]: {string_struct_new}
[STRING]   34 [   1]: {*lala*}
[STRING] ---- Dumping Used=2 End ----
## agrego primer nodo
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]    0 [   1] STATIC: {}
[STRING]   32 [   1]: {string_struct_new}
[STRING]   34 [   2]: {*lala*}
[STRING] ---- Dumping Used=3 End ----
## agrego segundo nodo
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]    0 [   2] STATIC: {}
[STRING]   32 [   1]: {string_struct_new}
[STRING]   34 [   2]: {*lala*}
[STRING]   35 [   1]: {*lala*_1}
[STRING] ---- Dumping Used=4 End ----
## agrego tercer nodo
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]    0 [   3] STATIC: {}
[STRING]   32 [   1]: {string_struct_new}
[STRING]   34 [   2]: {*lala*}
[STRING]   35 [   1]: {*lala*_1}
[STRING]   36 [   1]: {*lala*_2}
[STRING] ---- Dumping Used=5 End ----
#### free
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]    0 [   3] STATIC: {}
[STRING]   32 [   1]: {string_struct_new}
[STRING]   34 [   1]: {*lala*}
[STRING] ---- Dumping Used=3 End ----
# a() exit
[STRING] ---- Dumping MaxID=1056 strings ----
[STRING]    0 [   3] STATIC: {}
[STRING]   32 [   1]: {string_struct_new}
[STRING] ---- Dumping Used=2 End ----

como veras, al salir de a() todas las strings que no se retornan son liberadas...

que pasa actualmente con el uso de punteros a strings? que se generan y generan strings que no se liberan nunca de memoria, con lo que incrementa la memoria e incrementa e incrementa, hasta dar un "no hay mas memoria para allocar" o algo parecido.

los crash con respecto a strings *, no se debe a este problema, sino, seguramente a un uso desprolijo de los punteros, quizas no se setean a null luego de liberarlos y cuando se vuelven a acceder se piensa que hay valor, o usarlos como *pointer cuando valen NULL.

las nuevas funciones son

string * string_alloc()              - retorna un puntero a string conteniendo una string vacia
string * string_alloc(string)      - retorna un puntero a string asignando un valor a la string
string_release(string **)          - libera la string usada (contador de usos), libera de memoria el puntero a string, y setea el puntero a NULL (para evitar el mal uso y el olvido de setear el puntero a NULL se exige que el parametro sea string **)
string_dump()                        - funcion de debug, muestra las strings en uso, su id, contador de uso y string
any * string_buffer(string)                - retorna el char * directo al contenido de la string (esta funcion debe ser usada con cuidado, porque permite modificar las cadenas que son fijas del sistema/dcb)

por otro lado, la forma correcta de meter actualmente strings a punteros en estructuras es usando arrays de chars, o si no son a estructuras usar <string *> = &<string>

uso correcto actual

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


function char * string2buffer(string in, char *buf)
private
    int sz, i;
begin
    sz = strlen(in);
    if (!buf) buf = mem_alloc(sz+1); end
    for( i = 0; i < sz ; i++ ) buf[i] = in[i]; end
    buf[sz] = 0;
    return buf;
end

#define buffer2string(buf) ((string)(buf))

function split_string(string input, char **part1, char **part2)
private
    int i;
begin
    i = find(input," ");
    *part1 = string2buffer( substr( input, 0, i ), null );
    *part2 = string2buffer( substr( input, i + 1), null );
end

private
    char *pchar1, *pchar2;
    string string1 = "hello world", string2;
    char array1[128], array2[128];
begin

    say("--------------------------");
    say("- direct string <-> char[]");
    say("--------------------------");
    array1  = string1;                              say("array1  (from string)                              > '" + array1 + "'");
    string2 = array1;                               say("string2 (from array)                               > '" + string2 + "'");
    say("");

    say("------------------------");
    say("- safe string <-> char *");
    say("------------------------");
    pchar1  = string2buffer(string1,null);          say("pchar1  (from string2buffer with allocated return) > '" + (string) pchar1 + "' (" + pchar1 + ")");
    string2 = (string) pchar1;                      say("string2 (from cast char *)                         > '" + string2 + "'");
    string2 = buffer2string(pchar1); free(pchar1);  say("string2 (from buffer2string) (and free)            > '" + string2 + "'");
    say("");

    say("--------------------------------------------------------");
    say("- string <-> char[] with string2buffer and buffer2string");
    say("--------------------------------------------------------");
    string2buffer(string1,&array2);                 say("array2  (from string2buffer using array address)   > '" + array2 + "'");
    string2 = (string) &array2;                     say("string2 (from cast array address)                  > '" + string2 + "'");
    string2 = buffer2string(&array2);               say("string2 (from buffer2string)                       > '" + string2 + "'");
    say("");


    say("-----------------------------------");
    say("sample function safe string returns");
    say("-----------------------------------");
    split_string(string1, &pchar1, &pchar2 );

    say( "part1 > " + buffer2string(pchar1) );
    say( "part2 > " + buffer2string(pchar2) );

    free( pchar1 );
    free( pchar2 );

end


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


function split_string(string input, string *parts)
private
    int i;
begin
    i = find(input," ");
    parts[0] = substr( input, 0, i );
    parts[1] = substr( input, i + 1 );
end


function a()
private
    string string1 = "hello world";
    string parts[1];
begin
    string_dump();

    say("-----------------------------------");
    say("sample function safe string returns");
    say("-----------------------------------");
    split_string( string1, &parts );

    say( "part1 > " + parts[0] );
    say( "part2 > " + parts[1] );

    string_dump();

end

begin
    a();
    string_dump();
end
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 25, 2018, 04:25:07 am
tengo mas ejemplos, pero tengo que limpiarlos un poquito.
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: Drumpi en Enero 27, 2018, 01:12:12 am
Es un poco tarde para leer el código, pero aunque se parece a lo que hago, no es exactamente eso. En el enlace que puse tienes la "librería" (tiene un par de fallos en la ordenación de strings y algún caso que no me había dado cuenta de puntero a null, tengo que subir la versión corregida) y un código de ejemplo.
La "librería" es algo más complicada que eso que has escrito, porque tiene constructores, y destructores (destructores que vacían la string antes de hacer free, porque ya comentaste en su día algo similar de que no se liberaba la memoria), así como funciones de concatenación, filtrado, búsqueda, ordenación, etc, etc, que me han sido tremendamente útiles (hasta el punto de que reutilicé el código para almacenar una lista de carpetas y ficheros para crear navegadores de directorios).

Además, nunca uso CALLOC, siempre tiro de ALLOC, me parece más adecuado a lo que estoy acostumbrado a usar.

Respecto a los arrays de strings, el problema más común que he tenido siempre es cuando reservo espacio para varias cadenas, y relleno los datos para la primera, para la segunda, para la tercera... y en un momento dado, modifico la segunda, haciéndola más larga, y se me produce un segmentation fault, que yo he achacado siempre a que la memoria de la segunda cadena me ha pisado los datos de la tercera, y en ocasiones (raras, pero me ha pasado) memorias de variables de algún proceso, como la coordenada X, o una variable privada.
No me pidas ejemplos, porque no los tengo. Los corregí en su momento y nunca más se supo, y aislarlo me hubiera llevado horas, para evitar que al eliminar procesos, variables y demás, el error dejase de reproducirse por cambiar los espacios de memoria.
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: SplinterGU en Enero 28, 2018, 06:11:24 am
por el contrario, calloc es mas adecuado, porque aloca con la memoria limpia, lo que equivale a 0, null, y en el caso de strings, equivale a la string 0, que es "" y es del sistema, esa no importa que tenga contador de usos a cero, porque esa string nunca se descarga de memoria... y cuando le asignes un valor, el core no intentara descargar basura (u otra string) de memoria, el usar malloc en lugar de calloc, puede provocar (aunque no siempre) crashes/petes...

no se como descargas la string desde bennugd, porque no hay funcion para descargar strings a nivel de usuario... a menos que hagas magia... quizas una forma de que no ocupe memoria, seria hacer un *puntero_string = "" antes de hacer el free del puntero. Si bien incrementa el contador de usos de "" (string fija del sistema) puede hacer que se descargue el contador de usos de la string que apuntaba el puntero, y la librere de memoria cuando ya no la use... tendria que probarlo.

cuando lo tengas el codigo corregido, avisame y lo pruebo.
Título: Re:Duda strings, punteros y errores "string alloc: out of memory"
Publicado por: Drumpi en Febrero 03, 2018, 01:02:11 am
Hombre, free no hago, pero asignarle la cadena "" sí :D

¡Ah! ¿Estabas esperando la versión corregida? perdona ^^U Voy a buscarla y te la subo en cuanto pueda, que me has pillado de celebraciones cumpleañeras :P