Club Builder - Foros de discusión Club Builder
Foro de C++Builder en español
 
 FAQFAQ   BuscarBuscar   MiembrosMiembros   Grupos de UsuariosGrupos de Usuarios   RegistrarseRegistrarse 
 PerfilPerfil   Entra para ver tus mensajes privadosEntra para ver tus mensajes privados   EntrarEntrar 

Límite char*

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Consultas
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
Mensaje    Asunto: Límite char* Responder citando

Estoy utilizando una función que ataca un ActiveX. Esta función devuelve un char* que contiene un documento xml ó parte de éste.

El problema viene cuando la cadena devuelta tiene más de una longitud determinada.

la función es la siguiente

char* INeoXML_getNode(char* miXml, char* rutaNodo, char* sp, char* fo){

Variant xml;
AnsiString str;
AnsiString strLog;

try{
xml = CreateOleObject("INeoXML_E.funciones");
str = xml.OleFunction("getNode", miXml, rutaNodo, sp, fo);
xml = Unassigned;

return(char*)str.c_str();
}
catch(Exception &e){
xml = Unassigned;
return (char*)e.Message.c_str();
}
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Text = INeoXML_getNode("c:\\foo.xml", "DOC;FACTURA", ";", "");
}

Si aquí la longitud de la cadena devuelto por la función es demasiado grande el programa rompe.

Sin embargo si la función se encuentra dentro del cuerpo del programa, es decir el valor de la cadena lo recojo directamente del ActiveX

void __fastcall TForm1::Button1Click(TObject *Sender)
{

Variant xml;
AnsiString str;
AnsiString strLog;

try{
xml = CreateOleObject("INeoXML_E.funciones");
str = xml.OleFunction("getNode", "#c:\\crisp.xml", "crisp", ";", "");
xml = Unassigned;

Memo1->Text = str;
}
catch(Exception &e){
xml = Unassigned;
Memo1->Text = e.Message;
}
}

Aquí no hay ningún problema.

¿Dónde está mi fallo?

Gracias de antemano. Roberto.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

hola bobbylanuit, el problema es q el bloque de memoria que estas retornando fue creada localmente. yo modificaria de esta manera la funcion en el return usaria un int para retornar el tamaño del bloque asignado, agregaria un argumento mas a la funcion por ejemplo char *buf, quedaria algo asi
Código:
 int INeoXML_getNode(char* miXml, char* rutaNodo, char* sp, char* fo,char *buf){ ......}

dentro de la funcion usar new.
Código:
xml = CreateOleObject("INeoXML_E.funciones");
str = xml.OleFunction("getNode", miXml, rutaNodo, sp, fo);
buf = new char [str.Length()]; //para asignar memoria
...   
return (0); //si buf es NULL
....
...  //copiar str -> buf
...
... //compruebo que todo fue bien
return (str.Length());
}
lo que esta comentado sin codigo es la transferencia de datos al bloque de memoria asignado dinamicamente y algunos if else try, por ej verificar que new no sea null, para copiar datos podrias usar alguna funcion para bloques de memoria en realidad lo pongo muy generico porque hay muchas formas de hacerlo por ej (read write) cuando termines de usar los datos no te olvides de eliminar [buf] con un [delete].
saludos tor
_________________
Un experto es aquel que ya ha cometido todos los errores posibles en una materia muy concreta.
(Niels Bohr)
Volver arriba
Ver perfil de usuario Enviar mensaje privado MSN Messenger
Mensaje    Asunto: Responder citando

Para analizar con el codigo que posteas sin modificar, coloca un break point justo sobre
Código:
xml = Unassigned;
dentro del try. usa [Watches] o [inspector] para visualizar la variable y deberia estar todos los datos, la perdida se produce cuando las variables locales son descartadas, cuando finaliza la funcion. Prueba tambien
Código:
AnsiString str;
como global y deberia funcionar, no deberia cortarse la cadena como mencionas.
bye
_________________
Un experto es aquel que ya ha cometido todos los errores posibles en una materia muy concreta.
(Niels Bohr)
Volver arriba
Ver perfil de usuario Enviar mensaje privado MSN Messenger
Mensaje    Asunto: Responder citando

Cambia el valor de regreso de la cadena
de char * a String
Código:
String INeoXML_getNode(char* miXml, char* rutaNodo, char* sp, char* fo){

Variant xml;
AnsiString str;
AnsiString strLog;

try{
xml = CreateOleObject("INeoXML_E.funciones");
str = xml.OleFunction("getNode", miXml, rutaNodo, sp, fo);
xml = Unassigned;

return str; // // <--cambia aqui
}
catch(Exception &e){
xml = Unassigned;
return e.Message;  // <-- y cambia aqui
}
}

y usala normalmente

Código:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Text = INeoXML_getNode("c:\\foo.xml", "DOC;FACTURA", ";", "");
}

_________________
Cool
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email MSN Messenger
Mensaje    Asunto: Responder citando

Sois la caña de verdad. He probado a poner la variable AnsiString str como global y me ha funcionado a la primera.

En cuanto retornar un String no lo puedo utilizar ya que la función es para una dll que va a utilizar un programa que sólo "entiende" de variables primitivas. Pero de todas formas me sirve para saber a qué atenerme otras veces.

Muchísimas gracias.

La verdad que esto de la fe nunca ha sido lo mío...y bueno está bien que funcione pero ¿por qué?

¿Qué diferencia hay entre que la variable sea local ó global a la hora de retornar un resultado?

Un saludo. Roberto.

P.D. Cuando paseis por Zaragoza o Madrid tenéis un par de cañas pagadas (con tapa).
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

por lo general se intenta no usar variables globales o por lo menos usar los menos posible en los programas, pero no esta mal usarlos. El problema de la perdida de datos tiene que ver con el return de la funcion, un return solo puede retornar un valor "no puede retornar un verctor de valores (array)" lo que planteaba Cesar es cambiar a String, pasa que este tipo de dato es un objeto entonses en este caso estarias retornando un solo valor el objeto String completo, funcionaria = si rotornas el AnsiString sin la convercion a str q realizas en el return, ya que AnsiString tambien es un objeto, una cadena de caracteres es un vector return(char*)str.c_str(); lo que hace en realidad es retornar el puntero a el primer elemento solo un valor..
A nivel maquina los argumentos son pasados por la pila por lo tanto la funcion realiza con una o varias instruccion maquina "pop registro" para recuperarlos dependiendo de la cantidad de argumentos y el return lo devuelve por un registro, solo un registro.
Mira en este link http://www.elo.utfsm.cl/~lsb/elo311/clases/apuntes_c/Funciones.pdf hay algo sobre las funciones creo que te va a ayudar a entender mejor.
saludos tor
_________________
Un experto es aquel que ya ha cometido todos los errores posibles en una materia muy concreta.
(Niels Bohr)
Volver arriba
Ver perfil de usuario Enviar mensaje privado MSN Messenger
Mensaje    Asunto: Responder citando

mmmmm, vale. Entonces creo entender que el "trozo" de memoria para guardar variables globales es mayor que el "trozo" de memoria par las locales. ¿Es así?

Un saludo. Roberto.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

no eso es incorrecto, el bloque de memoria global(variables globales) no se destruye cuando sales de la funcion, cuando la funcion termina se liberan las variables q fueron creadas localmente, pero si en la funcion usas new de c++ o malloc, calloc de C tampoco se libera por eso el q hay que usar delete para C++ y free para C.
El libro de "B.Kernigan & D.Richie" trata el ansi C y esta muy bueno para afirmar los conocimientos en C.
saludos tor.
_________________
Un experto es aquel que ya ha cometido todos los errores posibles en una materia muy concreta.
(Niels Bohr)


Ultima edición por Tor el Mie 23 Ene, 2008 7:24 pm, editado 1 vez
Volver arriba
Ver perfil de usuario Enviar mensaje privado MSN Messenger
Mensaje    Asunto: Responder citando

Lo que tor cometa es que es mejor que devuelvas un tipo objeto como lo es String a devolver un tipo char*.

y sobre las variable esto funciona asi

Global - se conoce durante la vida del programa no se destruye hasta que el programa principal se cierra.
Local - se conoce solo y unicamente en la funcion o procedimiento que la crea

Código:
int x = 10;  // variable global

void muestra(void)
{
   int x = 4;  // variable local
   printf("%d",x+4); // esto muestra 8 pues usa la variable local
}
void main (void)
{
   printf("%d",::x); // esto muestra 10 usa la variable global
   muestra();  // muestra 8 pues usa su variable interna que es local
   printf("%d",::x+5); // esto muestra 15 usa la variable global
}

_________________
Cool
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email MSN Messenger
Mensaje    Asunto: Responder citando

Muchísimas gracias. Me habeis sido de gran ayuda.

Un saludo. Roberto.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mostrar mensajes de anteriores:   
Cambiar a:  
No puedes publicar temas nuevos en este foro
No puedes responder a temas en este foro
No puedes editar tus mensajes en este foro
No puedes borrar tus mensajes en este foro
No puedes votar en las encuestas de este foro


Hosting WordPress Indedmedia desde 3,99 €
© 2002–2026 Club Builder · Funciona con phpBB.