Cita:
|
Empezado por nlsgarcia
El siguiente programa funciona correctamente
|
No. Realmente no funciona bien.
Cita:
|
Empezado por nlsgarcia
¿Por que funciona si la declaración de RegPrnCmd, es a nivel global y falla si es declarada a nivel local?
|
No funciona de ninguna manera, es sólo que has tenido suerte, pero,
la programación no es cosa de suerte.
Cita:
|
Empezado por nlsgarcia
Como dije anteriormente es una pregunta teórica, el programa ya funciona pero me gustaría aclarar la duda
|
No, el programa aún no funciona y espero convencerte de ello para que no cargues con una bomba de tiempo que en algún momento te pueda estallar.
Es un problema interesante pues, a primera (y segunda) vista, no tiene sentido que sólo por cambiar el ámbito de la variable, deje de funcionar.
Ahora bien, puedes hacer que "funcione" usando la variable local simplemente declarándola
antes del File of TPrnCmd, y no después:
Código Delphi
[-]
function LogPrnCmd(LogFile, ProcPrnCmd, StatusProc : String) : Boolean;
var
i : integer;
RegPrnCmd : TPrnCmd;
f: File of TPrnCmd;
DateProc : String;
Bueno, pero
eso no puede ser una solución. Seguiría siendo una cuestión de suerte.
El error que obtienes es I/O error 6, que corresponde, como te comentó Lepe, a
Invalid File Handle. No es una cuestión de que el archivo no se encuentre, porque entonces obtendrías un error I/O error 2 (file not found) o 3 (path not found), pero no, tú obtienes un error que te dice que estás usando un descriptor de archivo incorrecto. Si hiciste una traza del programa te habrás dado cuenta que el error aparece en la línea:
Y, de hecho, el error lo genera FileSize. Pero si pones Seek(F, 28), el error lo genera Seek. Es decir, el error se genera cada vez que tratas de usar la variable F con alguna de las funciones de manejo de archivos. F es quien tiene el descriptor.
Ahora, ¿por qué está mal ese descriptor siendo que lo acabamos de crear con AssignFile?
Algo, lo está dañando. Está claro que ni Reset ni Rewrite pueden dañarlo; como dice Lepe, esos procedimientos están ahí desde los tiempos de Matusalén (perdón, de Niklas Wirth).
Lo único que hay entre la creación del descriptor y su uso son las asignaciones con StrPCopy. Y, como dijera Sherlock Holmes, cuando todo lo demás se ha descartado, lo que quede, por improbable que esto sea, es la verdad.
Vayamos a la documentación de StrPCopy:
Cita:
StrPCopy copies Source into a null-terminated string Dest. It returns a pointer to Dest.
StrPCopy does not perform any length checking.
The destination buffer must have room for at least Length(Source)+1 characters.
|
¡Ajá! ¿Notas el +1? Ese +1 está porque necesitas espacio para el caracter nulo de terminación de la cadena.
Tu código no hace ninguna verificación de la longitud de las cadenas que copias, aunque me parece que con las primeras no hay problema porque los datos que pasas son cortos. Aún así tienes que agregar código para verficar.
Pero la última copia:
Código Delphi
[-]
StrPCopy(RegPrnCmd.CRLF,chr(13)+chr(10));
es la que revienta todo. RegPrnCmd.CRLF está declarado como array [0..1] of char, esto es,
dos caracteres, y tú necesitas espacio para 2 (#13#10) + 1 (#0) caracteres. Entonces, StrPCopy escribe el caracter de terminación #0 en la parte de memoria que hay después del espacio asignado a RegPrnCmd.
Según creo recordar, las variables locales se guardan en el
stack o pila, así que, dependiendo del orden en que declares las variables, ese #0 sobreescribirá o no otra de las variables locales. Y una de esas variables, resulta ser la que contiene ¡el descriptor de archivo!
Si declaras la variable globalmente, no afecta al
stack pues se localizan en regiones distintas de la memoria. Pero es sólo por suerte, suerte de que el caracter de más no esté sobrescribiendo algo que afecte el programa.
// Saludos