![]() |
Error AccessViolation que no consigo localizar
Tengo un formulario con los siguientes componentes :
-Tquery -dataset -dbgrid Lo que hago es hacer una sql con la query y mostrar la en el GRID , una vez alli muestro los campos y tengo un checkbox dependiendo si lo chekeas o no hace una sql o otra. Un formulario realmente sencillo La cuestión es que en el gris empiezo a “toketearlo” y cada cierto número de veces que apreto en el grid , pueden ser 10..30..40 o 2… depende…. Me sale la siguiente excepción Project Proyecto1.exe raised exception class EAccessVioaltion with message ‘Access violation at address 004032AE in module Proyecto1.exe. Read of address FFFFFFDC’. Process stopped…. Alguna vez rara vez he visto esta otra Exception EAccessViolation in module Comerciales.exe at 00000000. Access violation at address 00000000. Read of Address 00000000 Os pondria el código pero sin la sql y tal no serviria de nada ;( he debugado y debugado pero no le veo el fallo.... salu2 radge |
Compila el código añadiendo opciones de Debug.
Una vez que estés ejecutando, prueba a ir a las opciones de Search/Find Error e introduce el primer número hexadecimal (address) a ver si por ahí aclaras algo. ![]() |
Adjunto imagen de las opciones que tengo al compilar
http://img258.imageshack.us/my.php?i...nttulo1ue9.jpg Con la dirección que me da la pongo dodne me has dicho y lo que me sale no se descifrarlo ![]() gracias , radge |
Hola, debes tener la informacion de debug activada (project->options->compiler->debug options) para que te indique encima de tu codigo en que linea te salta la excepción. Es mas, si pones en 'tools->debugger options->Halt on delphi exceptions', y pulsas Ctrl+F3 una vez te ha saltado la excepcion (dentro del IDE), sabras cuales han sido las funciones llamadas antes de la excepcion.
|
¿Tienes la pila de llamadas de ese error?
View/Debug Windows/Call Stack ¿Puedes ponerla? |
|
Os pongo un eskema de lo k hace mi evento FieldChanged del wwdbgrid que como vereis es muy simple
procedure formulario1.wwDBGrid1FieldChanged(Sender: TObject; Field: TField); begin if (condicion1) then begin SQL1 (INSERT INTO) SQL2 (UPDATE) end else begin Creo un formulario para rellenar unos datos y los recibo en el formulario actual Una vez recibido los datos lo destruyo. SQL3 (INSERT INTO) SQL4 (UPDATE) end; end gracias , radge |
si el fallo seguro que no esta en esquema, sino en algun detalle. Antes del codigo en el onchange, yo pondria
|
Cita:
Te refieres en el onfieldchanged ? Y eso que hace exactamente ? Porque yo no tengo ningun TDBEdit. Te referias al onchange del formulario o del dbgrid ? gracias , radge |
vaya, hubiese dicho que era dbedit. De igual manera, si, en el on fieldchange
PD : Read of address FFFFFFDC : Esto son ya las ultimas direcciones de memoria... creo que hay algo que no liberas correctamente y te va comiendo memoria. PDD : lo que hace es que evita calculos si no esta el formulario correctamente inicializado, etc...vamos, si no tiene el foco. Para evitar actualizaciones indeseadas o incontroladas mas bien. |
if not (sender as wwDBGrid1).focused then exit;
Me dice [Error] SupVision.pas(203): Operator not applicable to this operand type En cuanto lo de la memoria ya lo pensé yo pero lo unico que creo es un formulario que luego destruyo antes de volver a utilizarlo salu2 radge |
|
if not (sender as TDBGrid).Focused ... esto interpreta a 'sender' como de la clase DBGrid (si no lo fuera, por ejemplo si sender fuese un edit, te saltaria excepcion).
Pues en el momento que te salga la excepcion (en delphi, no en el programa) aprietas Ctrl+F3, te sale el stack. La primera linea es la ultima funcion llamada, y las siguientes las anteriores. El debugger te apunta a el codigo nativo pues es alli donde salta, aunque seguramente se haya provocado en una de las tuyas :entonces miras mediante esta lista cual de tus funciones ha sido la ultima en llamarse que ha provocado el error, y en que linea. Venga, suerte a ver si lo encuentras. |
Cita:
Entonces por eso no se donde pillar lo , porque no se lo que o donde lo esta provocando. salu2 radge |
a eso voy... cuando te salga la excepcion, aprietas Ctrl+F3 y te sale la lista de las llamadas a funciones. Olvidandote del codigo nativo, que esta correcto, tu vas a tu funcion y veras en que linea se te ha provocado y entonces puedes deducir porque. Saludos.
Cita:
esto anterior te hara saltar la excepcion en delphi aunque la tengas en un try Cita:
|
else if (FilaCheck = 'N') then
if (var1= var2) then begin botoseleccionat := MessageDlg('Estas seguro que quieres borrar las unidades servidas ?',mtCustom, [mbYes,mbNo], 0); if botoseleccionat = mrYes then begin cadenaSQL := 'update sql'; ModuloDatos.Ejecutar_SQL(cadenaSQL); cadenaSQL := 'update SQL'; ModuloDatos.Ejecutar_SQL(cadenaSQL); try query_supvision.Close; query_supvision.Open; except showmessage('Error abriendo la base de datos'); end end end He debugado y debugado y uno de las veces al mirar el "call stack" me marca en esta posición , pero yo no le veo nada a esta linea de codigo. gracias radge |
debugar es fastidioso :mad:, y hacerlo online, un poco mas :confused:. Otro truquito que se hace es ir comentando lineas, probando, comentando lineas, ... hasta que no te salte. Es raro, porque esa linea de codigo no tiene nada ciertamente...a no ser que, como deciamos, ya no tengas memoria ni para llenar un TModalResult...No se si cargas un exceso de datos por algun otro lado que no liberas, alguna form que creas varias veces en tiempo de ejecucion, querys que se crean y llaman multitud de veces (ejecutar_SQL) sin luego liberarlas,bitmaps,...ni idea, deberia repasar todo el codigo. Si tienes alguna otra duda, por eso, no dudes en ponerla aqui. Venga, saludos, i sort!;)
PD : prueba de ponerlo en otro evento que no sea el OnFieldChanged, pues ahora que pienso, si modificas la misma base de datos que se mira en el DBGrid, es probable que la llames recursivamente una y otra vez. Saludos. |
Si puedes, pon el codigo entero de
procedure formulario1.wwDBGrid1FieldChanged(Sender: TObject; Field: TField) Cita:
|
Código PHP:
|
puedes usar delphi y /delphi entre [], si es codigo delphi. Creas la form, pero en ningun momento la liberas. Yo lo haria asi:
casi seguro que es eso otra es marca, porque freeandnil si aun no se ha asignado (ni falta que hace)? TBookMarkStr solo es una string, por lo que en principio no te tienes que preocupar de su memoria. El access a nil es debido a eso seguro, pues la liberas y luego intentas trabajar con ella. Si quieres que tenga un valor nulo, simplemente haz marca := '' o marca := nil, pero no la liberes pues se queda desreferenciada en memoria. En tu caso, creo q no hace falta ni siquiera marca := '' pues a lo siguiente ya le das un valor concreto. Tambien creo q te falta un bloque begin end en ComboBox1.Text = 'TODOS' |
He cambiado lo que mas dicho del bloque begin y lo de la variable.
Pero lo del formulario lo he dejado asi
Pero sigue dandome error os dejo la pila. gracias radge Como veis todas las instrucciones son de código nativa menos la 1º empezando por abajo del stack , que es la marcada en rojo. ![]() ![]() |
Hay entre las llamadas del callstack algunas especiales:
![]() Creo que eso te puede dar datos sobre el campo del error. ¿Hay algun campo en el Grid en el que esté apareciendo "N"? ¿Tal vez un booleano? Deberías revisar si en algun momento ese campo puede no estar asignado. |
Hay entre las llamadas del callstack algunas especiales:
![]() Creo que eso te puede dar datos sobre el campo del error. ¿Hay algun campo en el Grid en el que esté apareciendo "N"? ¿Tal vez un booleano? Deberías revisar si en algun momento ese campo puede no estar asignado. |
Hola otra vez, probablemente ya tengas una instancia de TfrmUnidadesPedidoVenta con el nombre frmUnidadesPedidoVenta que se te crea de manera automatica (project->options->Forms->autocreateForms). Si es asi, al volver a usar ese nombre estas dejando toda la form anterior en memoria desreferenciada. Has probado si con el codigo anterior, tal cual esta, te salta el error? luego, al quedarse sin memoria, te puede saltar en cuqlquier momento. Tambien, query_supvision etc esta todo correcto no? en cuanto a creacion y liberacion.
|
Otra cosa: carregadades tambien esta todo correcto? si vas comentando bloques (por ejemplo, que no te cree el form o la parte de las consultas) te salta el error? es un metodo para localizarlo
|
Ok pruebo esto , de todas formas lo del formulario lo tengo en un try , me deberia saltar y no lo he visto saltar ninguna vez.
|
Bueno, segun la direccion de memoria que te pone (FFFFFFDC), ya casi al final de todo puede que consiga la memoria suficiente para la form, pero luego ya no pueda hacer nada mas, por lo que no tendria que saltar alli ($FFFFFFFF - $FFFFFFDC = $23 = 35 bytes) Por eso que te salte a las 30 o 40 veces. Yo creo que es eso, quiza me equivoque claro esta :p. Saludos
|
|
si te fijas, el stack son las funciones que se han ido llamando, que se guardan en esta lista. Asi, si quieres mirar donde ha saltado el error, pues va bien para conocer en que funcion. Ahora bien, segun tu dices te pasa a la 30 o 40 vez que pulsas el click, por lo que no es un error digamos inicial, sino uno que se va arrastrando. Asi pues, el stack aunque te diga donde ha saltado, el inicio del error puede estar en cualquier parte. Como ya te he dicho, yo creo que es porque creas algo repetidas veces sin liberarlo: has probado el codigo anterior, tal cual? f variable local, creandola con el create no con el application.createform, y su free? si aun asi te da error, prueba de comentar el bloque de creacion de esa form, a ver si asi te salta. si es el caso, entonces el error debe estar en alguna de las funciones interiores, carregadades, etc...donde quiza estes cargando datos en un objeto que creas repetidas veces pero no liberas cada vez.
|
ten en cuenta tambien la vision de Neftali: yo estoy fijo en lo de los 30 intentos, pero segun el stack que el te muestra, el error te saltaria por algo completamente diferente.
|
Cita:
Y tambien probé a poner : f := TfrmUnidadesPedidoVenta(create); En esa linia me pone [Error] SupVision.pas(203): Not enough actual parameters |
si bueno,... la sintaxis que es correcta seria -> f := TfrmUnidadesPedidoVenta.Create(nil) o (self), el argumento es el parent form, me debi liar al escribirlo. Igualmente, si al comentarlo (donde lo creas y donde la usas, claro, si es solo donde la creas tendras una excepcion mas) te sigue saltando, es que el error no esta por alla.
|
Cita:
salu2 radge |
X) pues tienes faena. saludos.
|
No si llevo más de 2 semanas con esto... pero es que no lo veo la verdad... me he trabado con ello.
gracias , radge |
mira en el codigo inicial que pusiste, he encontrado errores de los que yo considero graves (la liberacion del string que luego usas, crear una form con un nombre de variable global, probablemente ya creada,...), por lo que, sin animo de despreciar, creo que pueden haber bastantes del mismo tipo por diferentes lugares del proyecto. Le pegaria una repasada general a todo entero teniendo en cuenta :
- no crear forms inecesarias : si solo se usan una vez, usar el autocreate (project->options). Si se han de usar varias a la vez de la misma clase (como por ejemplo seria un preview), entonces si usar el create de las forms. - si se crean, en tiempo de ejecucion, tanto forms como otros objetos, destruirlos en la misma funcion desde donde se han llamado. Vamos, las ultimas lineas de la funcion tendrian que ser del tipo q.Free, f.Free,...(en teoria, si dentro de estas forms no creas nada en tiempo de ejecucion, no hace falta usar el free, pero no esta de mas) - si se cargan datos, tener en cuenta que se liberen una vez usados. Si se sale de la funcion donde se ha creado y cargado, entonces usar una variable global del form directamente y en su create darles la memoria (a todos los que vayas a usar) y en el create del objeto, hacer create(self) , o sea vinculado a la form, y en el evento destroy liberar estos objetos (solo en el destroy). Asi mientras este creada la form tendras esos objetos a mano siempre. - Lo que decia neftali, vigilar que los campos de tus query esten creados y correctamente escritos y llamados, y que se asignen valores de acuerdo a sus tipos. - Y lo que te comente al principio: usar los breakpoints (F5) los watches (Ctrl+F5), F7,F8 , el call stack, y lo de comentar/descomentar. Venga, haber si lo resuelves. Saludos |
Otra manera es usando un administrador de memoria y ir haciendo f7s,f8s...en los momentos en los que se te carguen bloques de memoria exagerados y alla se queden, por alla tendrias el problema (siempre suponiendo q el error sea por agotamiento de memoria, claro)
|
Como variable global creo esta "CodiClient" que es una variable que arrastro de un combobox a distintos sitios dentro del mismo formulario.
Lo del auto-create forms solo tengo uno llamado "splash" lo que salta al inicio del programa , solo tengo ese. El trozo este de codigo Código Delphi [-] Application.CreateForm (TfrmUnidadesPedidoVenta, frmUnidadesPedidoVenta); frmUnidadesPedidoVenta.CarregaDades(Cantidad,UnitatsServidesBD); frmUnidadesPedidoVenta.ShowModal; varDades := frmUnidadesPedidoVenta.rebreDades; varUnitatsRestants := frmUnidadesPedidoVenta.rebreUnitatsRestants; frmUnidadesPedidoVenta.Free;
|
pues quiza lo mas correcto sea q tengas en autocreate forms todas las forms que vas a usar en el proyecto. O es que las estas creando cada vez que las vas a llamar? si ese es el caso, una vez usadas y cerradas las forms, las destruyes?? porque ten en cuenta que si creas una form y luego vuelves a crearla y llamarla con el mismo nombre de variable sin haber destruido la anterior se queda esta ultima desreferenciada por memoria.
|
| La franja horaria es GMT +2. Ahora son las 00:53:10. |
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi