 |
Club Builder Foro de C++Builder en español
|
| Ver tema anterior :: Ver tema siguiente |
| Autor |
Mensaje |
bobbylanuit Ens

Registrado: 06 Jul 2005Mensajes: 31
|
Publicado: Mar 22 Ene, 2008 9:32 pm Asunto: Límite char* |
|
|
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 |
|
 |
Tor Master


Registrado: 22 Mar 2005Mensajes: 269Ubicación: obera, misiones, argentina
|
Publicado: Mie 23 Ene, 2008 2:25 am Asunto: |
|
|
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 |
|
 |
Tor Master


Registrado: 22 Mar 2005Mensajes: 269Ubicación: obera, misiones, argentina
|
Publicado: Mie 23 Ene, 2008 2:52 am Asunto: |
|
|
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 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 |
|
 |
Cesar C. Salazar Gonzalez Master


Registrado: 01 Oct 2002Mensajes: 2155Ubicación: San Cristóbal de Las Casas, Chiapas
|
Publicado: Mie 23 Ene, 2008 7:34 am Asunto: |
|
|
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", ";", "");
} |
_________________
 |
|
| Volver arriba |
|
 |
bobbylanuit Ens

Registrado: 06 Jul 2005Mensajes: 31
|
Publicado: Mie 23 Ene, 2008 10:11 am Asunto: |
|
|
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 |
|
 |
Tor Master


Registrado: 22 Mar 2005Mensajes: 269Ubicación: obera, misiones, argentina
|
Publicado: Mie 23 Ene, 2008 5:26 pm Asunto: |
|
|
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 |
|
 |
bobbylanuit Ens

Registrado: 06 Jul 2005Mensajes: 31
|
Publicado: Mie 23 Ene, 2008 6:52 pm Asunto: |
|
|
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 |
|
 |
Tor Master


Registrado: 22 Mar 2005Mensajes: 269Ubicación: obera, misiones, argentina
|
Publicado: Mie 23 Ene, 2008 7:12 pm Asunto: |
|
|
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 |
|
 |
Cesar C. Salazar Gonzalez Master


Registrado: 01 Oct 2002Mensajes: 2155Ubicación: San Cristóbal de Las Casas, Chiapas
|
Publicado: Mie 23 Ene, 2008 7:18 pm Asunto: |
|
|
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
} |
_________________
 |
|
| Volver arriba |
|
 |
bobbylanuit Ens

Registrado: 06 Jul 2005Mensajes: 31
|
Publicado: Mie 23 Ene, 2008 8:02 pm Asunto: |
|
|
Muchísimas gracias. Me habeis sido de gran ayuda.
Un saludo. Roberto. |
|
| Volver arriba |
|
 |
|
|
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
|
© 2002–2026 Club Builder · Funciona con phpBB.
|