Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Access Violation con dato tipo record (https://www.clubdelphi.com/foros/showthread.php?t=77649)

richy08 15-02-2012 16:54:02

Access Violation con dato tipo record
 
buenos dias compañeros tengo una duda que no he podido resolver y no encuentro informacion sobre esto, estoy revisando un codigo donde se crea un tipo record de esta forma

Código Delphi [-]
type
  TRegClienteProveedor = Record
    cCodigoCliente                      : Array[0..kLongCodigo] of Char;
    cRazonSocial                        : Array[0..kLongNombre] of Char;
    cFechaAlta                          : Array[0..kLongFecha] of Char;
    cRFC                                : Array[0..kLongRFC] of Char;
    cCURP                               : Array[0..kLongCURP] of Char;
    cDenComercial                       : Array[0..kLongDenComercial] of Char;
    cRepLegal                           : Array[0..kLongRepLegal] of Char;
    cNombreMoneda                       : Array[0..kLongNombre] of Char;
    cListaPreciosCliente                : LongInt;
    cDescuentoMovto                     : Double;
    cBanVentaCredito                    : LongInt; // 0 = No se permite venta a crédito, 1 = Se permite venta a crédito
    cCodigoValorClasificacionCliente1   : Array[0..kLongCodValorClasif] of Char;
    cCodigoValorClasificacionCliente2   : Array[0..kLongCodValorClasif] of Char;
    cCodigoValorClasificacionCliente3   : Array[0..kLongCodValorClasif] of Char;
    cCodigoValorClasificacionCliente4   : Array[0..kLongCodValorClasif] of Char;
    cCodigoValorClasificacionCliente5   : Array[0..kLongCodValorClasif] of Char;
    cCodigoValorClasificacionCliente6   : Array[0..kLongCodValorClasif] of Char;
    cTipoCliente                        : LongInt; // 1 - Cliente, 2 - Cliente/Proveedor, 3 - Proveedor
    cEstatus                            : LongInt; // 0. Inactivo, 1. Activo
    cFechaBaja                          : Array[0..kLongFecha] of Char;
    cFechaUltimaRevision                : Array[0..kLongFecha] of Char;
    cLimiteCreditoCliente               : Double;
    cDiasCreditoCliente                 : LongInt;
    cBanExcederCredito                  : LongInt; // 0 = No se permite exceder crédito, 1 = Se permite exceder el crédito
    cDescuentoProntoPago                : Double;
    cDiasProntoPago                     : LongInt;
    cInteresMoratorio                   : Double;
    cDiaPago                            : LongInt;
    cDiasRevision                       : LongInt;
    cMensajeria                         : Array[0..kLongDesCorta] of Char;
    cCuentaMensajeria                   : Array[0..kLongDescripcion] of Char;
    cDiasEmbarqueCliente                : LongInt;
    cCodigoAlmacen                      : Array[0..kLongCodigo] of Char;
    cCodigoAgenteVenta                  : Array[0..kLongCodigo] of Char;
    cCodigoAgenteCobro                  : Array[0..kLongCodigo] of Char;
    cRestriccionAgente                  : LongInt;
    cImpuesto1                          : Double;
    cImpuesto2                          : Double;
    cImpuesto3                          : Double;
    cRetencionCliente1                  : Double;
    cRetencionCliente2                  : Double;
    cCodigoValorClasificacionProveedor1 : Array[0..kLongCodValorClasif] of Char;
    cCodigoValorClasificacionProveedor2 : Array[0..kLongCodValorClasif] of Char;
    cCodigoValorClasificacionProveedor3 : Array[0..kLongCodValorClasif] of Char;
    cCodigoValorClasificacionProveedor4 : Array[0..kLongCodValorClasif] of Char;
    cCodigoValorClasificacionProveedor5 : Array[0..kLongCodValorClasif] of Char;
    cCodigoValorClasificacionProveedor6 : Array[0..kLongCodValorClasif] of Char;
    cLimiteCreditoProveedor             : Double;
    cDiasCreditoProveedor               : LongInt;
    cTiempoEntrega                      : LongInt;
    cDiasEmbarqueProveedor              : LongInt;
    cImpuestoProveedor1                 : Double;
    cImpuestoProveedor2                 : Double;
    cImpuestoProveedor3                 : Double;
    cRetencionProveedor1                : Double;
    cRetencionProveedor2                : Double;
    cBanInteresMoratorio                : LongInt; // 0 = No se le calculan intereses moratorios al cliente, 1 = Si se le calculan intereses moratorios al cliente.
    cTextoExtra1                        : Array[0..kLongTextoExtra] of Char;
    cTextoExtra2                        : Array[0..kLongTextoExtra] of Char;
    cTextoExtra3                        : Array[0..kLongTextoExtra] of Char;
    cFechaExtra                         : Array[0..kLongFecha]  of Char;
    cImporteExtra1                      : Double;
    cImporteExtra2                      : Double;
    cImporteExtra3                      : Double;
    cImporteExtra4                      : Double;
  end {RegClienteProveedor};

e inmediatamente crean una variable de ese tipo record asi
Código Delphi [-]
LPFREGCTEPROV =  ^TRegClienteProveedor;
mi pregunta es que significa este simbolo ^, por que al tratar de mandar este record a una funcion que se encuantra en el sdk de contpaq i para el cfdi me marca violacion de memoria



Código Delphi [-]
var
lError, entero : Integer;
.
.
.

datos1.cCodigoCliente[0]:='3';
datos1.cRazonSocial[0]:='3';
datos1.cFechaAlta:='3';
.
.
.
.
.
.
 entero:=3;
    

    lError :=fAltaCteProv(entero, datos1);


    if lError <> kSIN_ERRORES  then
    begin
      rMensajeError( lError );
      Exit;
    end;

gracias por cualquier comentario

roman 15-02-2012 17:06:09

Cita:

Empezado por richy08 (Mensaje 425223)
e inmediatamente crean una variable de ese tipo record asi
Código Delphi [-]
LPFREGCTEPROV =  ^TRegClienteProveedor;

Aquí no estás creando ninguna variable, sino declarando un tipo de datos. Las variables de tipo LPFREGCTEPROV serían apuntadores a variables del tipo record. El caret, ^, significa apunta a.

Tendrías que declarar una variabe de ese tipo:

Código Delphi [-]
var
  P: LPFREGCTEPROV;

Y, una de dos, asignar a dicha variable la direccción de un registro ya existente o bien asignarle memoria con New o GetMem.

// Saludos

richy08 15-02-2012 18:55:54

Gracias roman por la aclaracion creo que andaba muy perdido, hice el codigo asi y ya inserta el sdk pero a parte del valor que le doy para el campo me pone otros caracteres que me hacen pensar que pasa algo con la memoria el codigo que uso es este

Código Delphi [-]
var
lError, entero : Integer;
datos1 :LPFREGCTEPROV;
.
.
.
.

     GetMem(datos1, SizeOf(TRegProducto));
     datos1.cCodigoCliente[0]:='3';
     datos1.cRazonSocial[0]:='3';
     datos1.cFechaAlta:='02132012';


    datos1.cRFC:='3';
    datos1.cCURP:='3' ;
    datos1.cDenComercial :='3' ;
    datos1.cRepLegal:='3' ;
    datos1.cNombreMoneda:='3' ;

lError :=fAltaCteProv(entero, datos1);


    if lError <> kSIN_ERRORES  then
    begin
      rMensajeError( lError );
      Exit;
    end;

    showmessage(inttostr(entero));
    FreeMem(datos1);

existe algo en este codigo que pueda ocasionarme este comportamiento

mil gracias

roman 15-02-2012 19:04:36

¿Cuál campo? ¿En dónde es que te muestra caracteres extraños?

// Saludos

richy08 15-02-2012 19:31:18

Cita:

Empezado por roman (Mensaje 425233)
¿Cuál campo? ¿En dónde es que te muestra caracteres extraños?

// Saludos

perdon se me olvido especificar el campo, con esta instruccion mando los datos a una funcion del sdk del contpaq

Código Delphi [-]
lError :=fAltaCteProv(entero, datos1);


donde datos1.cCodigoCliente[0]:='3'; escribe sobre el campo llamado CIDCLIEN01 de la tabla MGW10002.dbf que es un campo caracter de longitud 30
y si abro el contpaqi factura electronica si esta el registro guardaro pero en el campo su valor me muestra esto 3$otrocarcterextraño

roman 15-02-2012 20:05:25

Cita:

Empezado por richy08 (Mensaje 425235)
donde datos1.cCodigoCliente[0]:='3';

¿Por qué haces así la asignación? Aunque sea sólo un caracter, debería ser

Código Delphi [-]
datos1.cCodigoCliente:='3';

y lo mismo en todos los demás campos similares.

// Saludos

richy08 15-02-2012 20:09:26

Cita:

Empezado por roman (Mensaje 425236)
¿Por qué haces así la asignación? Aunque sea sólo un caracter, debería ser

Código Delphi [-]datos1.cCodigoCliente:='3';


y lo mismo en todos los demás campos similares.

// Saludos


en la definicion del record esta asi

Código Delphi [-]
type   TRegClienteProveedor = Record     cCodigoCliente                      : Array[0..kLongCodigo] of Char;

al parecer esta guardando un arreglo de caracteres donde kloncodigo es una constante con el valor de 30, es por eso que lo asigno de esta manera

Código Delphi [-]
datos1.cCodigoCliente[0]:='4';

no se si esta correcto??, me supongo que la funcion es capaz de insertar multiples clientes en una sola llamada

tienes razon al cambiar la asignacion de esta forma

Código Delphi [-]
datos1.cCodigoCliente:='4';

ya no inserta caracteres extraños, lo cual me surge una duda el codigo en el que me estoy basando fue programado por una persona de contpaq, lo mas extraño es que no tiene ejemplos de insercciones por lo cual no se que tan correcto sea dejar el record con ese estructura

mil gracias roman por tu tiempo

roman 15-02-2012 21:13:40

Con seguridad, la empresa tendrá más de 10 clientes, así que es de esperar que el campo datos1.cCodigoCliente admita más de un caracter. Estrictamente hablando, no tengo manera de saber qué es lo que hace el programador original con el valor de ese registro. Pero como aparece basura (caracteres extra no identificados) en el campo final, es de sospecharse que dichos valores los está mandando como cadenas de caracteres.

En Delphi, un arreglo de Char, que comience con índice 0, es compatible con un string, y de ahí que puedas hacer la asignación:

Código Delphi [-]
datos1.cCodigoCliente:='4';

o bien

Código Delphi [-]
datos1.cCodigoCliente:='4084';

Si en la declaración del tipo de datos TRegClienteProveedor cambias el campo

Código Delphi [-]
cCodigoCliente                      : Array[0..kLongCodigo] of Char;

por

Código Delphi [-]
cCodigoCliente                      : Array[1..kLongCodigo] of Char;

verás que ni siquiera te permite compilar cuando haces una asignación como la de arriba.

Ahora bien, cuando usas cadenas de caracteres en un registro asignado dinámicamente (como es tu caso, al asignar memoria), no conviene usar el tipo de datos string ya que éste es, en el fondo, un apuntador, y, como tal, mide 4 bytes, por lo que la llamada a

Código Delphi [-]
GetMem(datos1, SizeOf(TRegProducto));

te daría un tamaño incorrecto. Por ello, en estos casos conviene usar tipos de datos de longitud fija, y quizá por ello el programador original escogió usar esos arreglos de caracteres.

Sin embargo, no es la única manera y quizá podrías sustituir esos arreglos por cadenas de longitud fija:

Código Delphi [-]
cCodigoCliente                      : string[kLongCodigo];

// Saludos

richy08 15-02-2012 22:37:20

gracias roman por la explicacion :D


La franja horaria es GMT +2. Ahora son las 22:43:58.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi