fallo en hb_xfree

fallo en hb_xfree

Postby Verhoven » Fri Jul 26, 2013 5:11 pm

El siguiente código devuelve error y no soy capaz de dar con una solución:

Code: Select all  Expand view  RUN
/* 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.
}
Verhoven
 
Posts: 521
Joined: Sun Oct 09, 2005 7:23 pm

Re: fallo en hb_xfree

Postby Antonio Linares » Fri Jul 26, 2013 6:44 pm

Que error te da ?

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

Code: Select all  Expand view  RUN
#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
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: fallo en hb_xfree

Postby Antonio Linares » Fri Jul 26, 2013 6: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
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: fallo en hb_xfree

Postby Verhoven » Fri Jul 26, 2013 6:52 pm

El problema me lo ha dado en ejecución. Voy a probar añadir ese + 1 a ver si es por eso
Verhoven
 
Posts: 521
Joined: Sun Oct 09, 2005 7:23 pm

Re: fallo en hb_xfree

Postby Verhoven » Fri Jul 26, 2013 6:55 pm

Pero creo que el problema no debería ser el +1 porque ese ya está incluido en nSize.
Verhoven
 
Posts: 521
Joined: Sun Oct 09, 2005 7:23 pm

Re: fallo en hb_xfree

Postby Antonio Linares » Fri Jul 26, 2013 6:55 pm

Otra forma más sencilla:

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

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: fallo en hb_xfree

Postby Antonio Linares » Fri Jul 26, 2013 7: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: Select all  Expand view  RUN
#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
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: fallo en hb_xfree

Postby Antonio Linares » Fri Jul 26, 2013 7:06 pm

Esta línea la puedes simplificar asi:

* pIndex = 0;
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: fallo en hb_xfree

Postby Verhoven » Sat Jul 27, 2013 10:27 am

Va perfectamente Antonio.
La copio a continuación para todo aquel que le pueda servir:

Code: Select all  Expand view  RUN

#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

 
Verhoven
 
Posts: 521
Joined: Sun Oct 09, 2005 7:23 pm

Re: fallo en hb_xfree

Postby xmanuel » 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: Select all  Expand view  RUN

    /* 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
xmanuel
 
Posts: 762
Joined: Sun Jun 15, 2008 7:47 pm
Location: Sevilla

Re: fallo en hb_xfree

Postby xmanuel » Sat Jul 27, 2013 10:44 am

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

abcd23htpl67w por ejemplo
______________________________________________________________________________
Sevilla - Andalucía
xmanuel
 
Posts: 762
Joined: Sun Jun 15, 2008 7:47 pm
Location: Sevilla

Re: fallo en hb_xfree

Postby Verhoven » 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.
Verhoven
 
Posts: 521
Joined: Sun Oct 09, 2005 7:23 pm

Re: fallo en hb_xfree

Postby Antonio Linares » Sat Jul 27, 2013 1: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: Select all  Expand view  RUN
#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
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: fallo en hb_xfree

Postby xmanuel » 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: Select all  Expand view  RUN

    #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
xmanuel
 
Posts: 762
Joined: Sun Jun 15, 2008 7:47 pm
Location: Sevilla

Re: fallo en hb_xfree

Postby Antonio Linares » Sun Jul 28, 2013 2: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
User avatar
Antonio Linares
Site Admin
 
Posts: 42118
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Next

Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 44 guests