FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour fallo en hb_xfree
Posts: 563
Joined: Sun Oct 09, 2005 07:23 PM
fallo en hb_xfree
Posted: Fri Jul 26, 2013 05:11 PM
El siguiente código devuelve error y no soy capaz de dar con una solución:

Code (fw): Select all Collapse
/* STR_EXTRAECARACTERES   OJO ESTÁ FALLANDO EN hb_xfree(cadena)
   Devuelve la parte de caracteres de una cadena.
*/
HB_FUNC( STR_EXTRAECARACTERES )
{
   size_t nSize;
   char *cadena;      // Contendrá una copia para trabajar de la cadena pasada a la función
       
   nSize = strlen( hb_parc( 1 ) )+1; //Suma uno para incluir el caracter de final de cadena='\0'
   //cadena=(char *)malloc(nSize);     // Reserva la memoria para la variable: cadena.
   cadena=(char *)hb_xgrab(nSize);
      
   memcpy( ( void * ) cadena, ( void * ) hb_parc( 1 ), nSize );
  
   while ( *cadena && !isdigit(*cadena) )
         cadena++;
   
   *cadena='\0';
   
   //Devuelve la cadena al prg:
   //MessageBox( GetActiveWindow(), result, "Resultado:", 0x40 );
   hb_retc( cadena );       
   hb_xfree(cadena);  //Libera la memoria reservada para la variable: cadena
                      // hb_xfree(cadena) Si se usa esta de Harbour es más seguro el liberado.
}
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: fallo en hb_xfree
Posted: Fri Jul 26, 2013 06:44 PM
Que error te da ?

Aqui compila bien asi, añadiendo solo los ficheros de cabecera y el pragma BEGINDUMP ... ENDDUMP:

Code (fw): Select all Collapse
#pragma BEGINDUMP

#include <hbapi.h>
#include <windows.h>

HB_FUNC( STR_EXTRAECARACTERES )
{
   size_t nSize;
   char *cadena;      // Contendrá una copia para trabajar de la cadena pasada a la función
       
   nSize = strlen( hb_parc( 1 ) )+1; //Suma uno para incluir el caracter de final de cadena='\0'
   //cadena=(char *)malloc(nSize);     // Reserva la memoria para la variable: cadena.
   cadena=(char *)hb_xgrab(nSize);
      
   memcpy( ( void * ) cadena, ( void * ) hb_parc( 1 ), nSize );
  
   while ( *cadena && !isdigit(*cadena) )
         cadena++;
   
   *cadena='\0';
   
   //Devuelve la cadena al prg:
   //MessageBox( GetActiveWindow(), result, "Resultado:", 0x40 );
   hb_retc( cadena );       
   hb_xfree(cadena);  //Libera la memoria reservada para la variable: cadena
                      // hb_xfree(cadena) Si se usa esta de Harbour es más seguro el liberado.
}

#pragma ENDDUMP
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: fallo en hb_xfree
Posted: Fri Jul 26, 2013 06:47 PM

Aqui tambien podria faltarte añadir un byte más:

memcpy( ( void * ) cadena, ( void * ) hb_parc( 1 ), nSize + 1 );

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 563
Joined: Sun Oct 09, 2005 07:23 PM
Re: fallo en hb_xfree
Posted: Fri Jul 26, 2013 06:52 PM

El problema me lo ha dado en ejecución. Voy a probar añadir ese + 1 a ver si es por eso

Posts: 563
Joined: Sun Oct 09, 2005 07:23 PM
Re: fallo en hb_xfree
Posted: Fri Jul 26, 2013 06:55 PM

Pero creo que el problema no debería ser el +1 porque ese ya está incluido en nSize.

Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: fallo en hb_xfree
Posted: Fri Jul 26, 2013 06:55 PM

Otra forma más sencilla:

strcpy( ( char * ) cadena, ( char * ) hb_parc( 1 ) );

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: fallo en hb_xfree
Posted: Fri Jul 26, 2013 07:03 PM
Tienes razón con nSize, y el fallo es muy sutil :-)

Estas modificando cadena! No puedes hacer eso, o no devolveras correctamente su comienzo :-)

Code (fw): Select all Collapse
#pragma BEGINDUMP

#include <hbapi.h>
#include <windows.h>

HB_FUNC( STR_EXTRAECARACTERES )
{
   char * cadena = ( char * ) hb_xgrab( hb_parclen( 1 ) + 1 );      // Contendrá una copia para trabajar de la cadena pasada a la función
   char * pIndex = cadena;    
       
   strcpy( cadena, hb_parc( 1 ) );     
       
   while ( * pIndex && ! isdigit( * pIndex ) )
      pIndex++;
   
   * pIndex = '\0';
   
   hb_retc( cadena );       
   hb_xfree( ( void * ) cadena );  //Libera la memoria reservada para la variable: cadena
                        // hb_xfree(cadena) Si se usa esta de Harbour es más seguro el liberado.
}

#pragma ENDDUMP
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: fallo en hb_xfree
Posted: Fri Jul 26, 2013 07:06 PM

Esta línea la puedes simplificar asi:

  • pIndex = 0;
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 563
Joined: Sun Oct 09, 2005 07:23 PM
Re: fallo en hb_xfree
Posted: Sat Jul 27, 2013 10:27 AM
Va perfectamente Antonio.
La copio a continuación para todo aquel que le pueda servir:

Code (fw): Select all Collapse
#pragma BEGINDUMP
#include "hbapi.h"
#include "windows.h"
#include "string.h"

/* STR_EXTRAECARACTERES
   Devuelve la parte de caracteres inicial de una cadena que contenga números a partir de
    un cierto caracter. Ejemplo de uso desde un PRG:
    
    STR_EXTRAECARACTERES( "cParteCaracteres0123" )  --> cParteCaracteres
*/
HB_FUNC( STR_EXTRAECARACTERES )
{
   char *cadena = (char *)hb_xgrab( hb_parclen(1)+1 ); // Contendrá una copia para trabajar de la cadena pasada a la función
   char *pIndex = cadena;                              // Suma uno para incluir el caracter de final de cadena='\0'
       
   strcpy( cadena, hb_parc(1) );
  
   while ( *pIndex && !isdigit(*pIndex) )
        pIndex++;
   
   *pIndex = 0;   
   
   //Devuelve la cadena al prg recortada hasta donde empiezan los dígitos:
   //MessageBox( GetActiveWindow(), cadena, "Resultado:", 0x40 );
   hb_retc( cadena );       
   hb_xfree( (void *)cadena );  //Libera la memoria reservada para la variable: cadena
}
#pragma ENDDUMP
Posts: 817
Joined: Sun Jun 15, 2008 07:47 PM
Re: fallo en hb_xfree
Posted: Sat Jul 27, 2013 10:36 AM
Una pregunta para ver si yo te puedo ayudar...

Qué hace la función?

Si lo que hace es estraer caracteres no debería ser algo así:

Code (fw): Select all Collapse
    /* STR_EXTRAECARACTERES   OJO ESTÁ FALLANDO EN hb_xfree(cadena)
       Devuelve la parte de caracteres de una cadena.
    */
    HB_FUNC( STR_EXTRAECARACTERES )
    {
       size_t nSize = hb_parclen( 1 ) + 1;
       char *cadena = hb_parc( 1 );      // Contendrá una copia para trabajar de la cadena pasada a la función
       char *wCadena =  (char *) hb_xgrab( nSize );   
    
       while ( *cadena && !HB_ISDIGIT(*cadena) )
       {
             *wCadena++ = *cadena++;    
       }
       *wCadena++ = '\0';
       
       //Devuelve la cadena al prg:
       //MessageBox( GetActiveWindow(), result, "Resultado:", 0x40 );
       hb_retc( wCadena );      
       hb_xfree(wCadena);  //Libera la memoria reservada para la variable: cadena
    }
______________________________________________________________________________

Sevilla - Andalucía
Posts: 817
Joined: Sun Jun 15, 2008 07:47 PM
Re: fallo en hb_xfree
Posted: Sat Jul 27, 2013 10:44 AM

Creo que tu función original no funcionaría con esto:

abcd23htpl67w por ejemplo

______________________________________________________________________________

Sevilla - Andalucía
Posts: 563
Joined: Sun Oct 09, 2005 07:23 PM
Re: fallo en hb_xfree
Posted: Sat Jul 27, 2013 11:02 AM

Gracias Manuel, pero si ves el código de los mensajes de Antonio que quedan incorporados al último post anterior mío el programa ha quedado funcionando bien.

El asunto consiste en que hay un programa que genera datos en un fichero muy grande y necesito ir separando los comando (alfabético solo) de sus valores (dígitos decimales). Como es un volumen muy grande de datos necesito una función C que lo haga lo más rápido posible, y se nota de hecho que es más rápido desarrollado en C. Las cadenas me llegan como: CmdCRKg00123 y necesito sacar por un lado la parte de caracteres y por otro la del número, de ahí la necesidad de desarrollar esa función.

Lo que hago es con el puntero que manda el PRG a la función C mediante hb_parc( nº de orden del argumento pasado a la función ) copiar los datos a una variable nueva dentro del código C para trabajar con ella:
Primero se reserva memoria para una variable llamada "cadena" donde se copiará la cadena, valga la redundancia, pasada a la función C.
Se copia la cadena pasada a la función a esa variable.
Se va inspeccionando caracter por caracter para ver si es un dígito.
Cuando encuentra el primer dígito coloca en esa posición una marca de final de cadena '\0': con pIndex = '\0' ó pIndex = 0.
Devuelve al PRG el puntero de la variable "cadena", modificada con ese '\0' insertado, de forma que el PRG cuando lo encuentre da por concluida la cadena en esa posición de memoria omitiendo con ello la parte numérica de la cadena original.
Termina liberando la memoria reservada para la variable cadena.

Se tarda más en explicarlo que en hacerlo.

Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: fallo en hb_xfree
Posted: Sat Jul 27, 2013 01:10 PM
Verhoven,

Si vas a procesar un gran número de cadenas, puedes acelerar el proceso evitando llamar a hb_xgrab() y hb_xfree() que son lentos en procesos muy repetitivos.

Quedaría asi:
Code (fw): Select all Collapse
#pragma BEGINDUMP
#include "hbapi.h"
#include "windows.h"
#include "string.h"

HB_FUNC( STR_EXTRAECARACTERES )
{
   char * cadena = ( char * ) hb_parc( 1 ); 
   char * pIndex = cadena; 
       
   while ( * pIndex && ! isdigit( * pIndex ) )
        pIndex++;
   
   hb_retclen( cadena, pIndex - cadena );       
}

#pragma ENDDUMP
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 817
Joined: Sun Jun 15, 2008 07:47 PM
Re: fallo en hb_xfree
Posted: Sun Jul 28, 2013 12:57 PM
Antonio,el propotipo de hb_retclen es este:

hb_retclen( const char * szText, HB_SIZE nLen );

Por tanto no sería así?
Code (fw): Select all Collapse
    #pragma BEGINDUMP
    #include "hbapi.h"
    #include "windows.h"
    #include "string.h"

    HB_FUNC( STR_EXTRAECARACTERES )
    {
       char * cadena = ( char * ) hb_parc( 1 );
       HB_SIZE ilen = hb_parclen( 1 );
       HB_SIZE iIndex = 0;
           
       while ( * cadena && ! isdigit( * cadena ) ) {
            iIndex++;
            *cadena++;
       }
       
       hb_retclen( cadena, iLen - iIndex);      
    }

    #pragma ENDDUMP
______________________________________________________________________________

Sevilla - Andalucía
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: fallo en hb_xfree
Posted: Sun Jul 28, 2013 02:12 PM

Manuel,

Al restarle a un puntero el valor del otro puntero, obtenemos su "distancia" en bytes ya que ambos "apuntaban" al mismo lugar originalmente :-)

Y esa distancia (ó longitud) es precisamente el segundo parámetro (nLen) que espera hb_retclen()

regards, saludos

Antonio Linares
www.fivetechsoft.com