Avatar billede dkklein Nybegynder
05. januar 2002 - 13:24 Der er 31 kommentarer og
2 løsninger

Access violation fejl

Jeg er ved at lave et program som anvender en ekstern dll.

Følgende som er i mit hovedprogram fejler samme sted hver gang med en access violation:

var status1,status2: Integer;
    tkjevent : scauto_event;
begin
  status1 := scauto_connect(\'tkj\', \'10.0.0.100.12690\', \'mrtg\' , \'All\');
  status2 := scauto_query(\'tkj\', \'\', \'all\',tkjevent);


scauto_connect og scauto_query er defineret således i et andet unit:

type
    Pscauto_event = ^scauto_event;
    scauto_event = packed record
        evfields : string;
        evtype : string[16];
        evtime : string[17];
        evsysseq : string[32];
        evusrseq : string[32];
        evsysopt : string[24];
        evuser : string[24];
        evpswd : string[24];
        evsepchar : Char;
    end;   

function scauto_connect(Id: string; Server: string; Events: string; Users: string) : Integer;
function scauto_query(Id: string; Start: string; Opt: string; var Event: scauto_event) : Integer;

type
    {* This is what the DLL really wants to see *}
    real_scauto_event = packed record
        evfields: PAnsiChar;
        evtype: array[0..16] of AnsiChar;
        evtime: array[0..17] of AnsiChar;
        evsysseq: array[0..32] of AnsiChar;
        evusrseq: array [0..32] of AnsiChar;
        evsysopt: array [0..24] of AnsiChar;
        evuser: array [0..24] of AnsiChar;
        evpswd: array [0..24] of AnsiChar;
        evsepchar: AnsiChar;
    end;

procedure real_to_fake(var real_ev : real_scauto_event; var fake_ev : scauto_event);
begin
    fake_ev.evtype := string(real_ev.evtype);
    fake_ev.evsysseq := string(real_ev.evsysseq);
    fake_ev.evusrseq := string(real_ev.evusrseq);
    fake_ev.evtime := string(real_ev.evtime);
    fake_ev.evsysopt := string(real_ev.evsysopt);
    fake_ev.evuser := string(real_ev.evuser);
    fake_ev.evsepchar := real_ev.evsepchar;
    fake_ev.evfields := string(real_ev.evfields);
end;


function real_scauto_connect(Id: PChar; Server: PChar; Events: PChar; Users: PChar) : Integer;
    stdcall; external \'scauto.dll\' name \'scauto_connect\';

function real_scauto_query(Id: PChar; Start: PChar; Opt: PChar; var Event: real_scauto_event) : Integer;
    stdcall; external \'scauto.dll\' name \'scauto_query\';

function scauto_connect(Id: string; Server: string; Events: string; Users: string) : Integer;
begin
  scauto_connect := real_scauto_connect(PChar(Id), PChar(Server),
                    PChar(Events), PChar(Users));
end;

function scauto_query(Id: string; Start: string; Opt: string; var Event: scauto_event) : Integer;
var real_ev : real_scauto_event;
    status : Integer;
begin
    status := real_scauto_query(PChar(Id), PChar(Start), PChar(Opt), real_ev);
    if status = 0 then
        real_to_fake(real_ev, Event);
    scauto_query := status;
end;

Mit program fejler HVER gang ved udførelsen af scauto_query := status; i funtionen scauto_query

Hvad overser jeg?

ps jeg har kun pillet det ud fra min kode som jeg mener er relevant.
Avatar billede easysoft_studios Nybegynder
05. januar 2002 - 13:29 #1
prøv at lave dummy function og procedure. Altså en function der bare smider noget tilbage - her mener jeg man skal stdcall eller noget i den retning, ellers Access Violation\'ereenne den...!
Og prøv en procedure der bare siger \'Godddag!\', med ShowMessage();

Prøv!
Avatar billede dkklein Nybegynder
05. januar 2002 - 13:31 #2
Øhh, hvad skulle det gøre godt for?
Avatar billede easysoft_studios Nybegynder
05. januar 2002 - 13:35 #3
for at se om den stadig siger Access Violation - for hvis den gør så mangler du noget bindeled af en art. Jeg brugte selv meget tid på at få vanskelige functions til at køre i DLL\'er!
Avatar billede dkklein Nybegynder
05. januar 2002 - 13:38 #4
Den eksterne routine fungerer korrekt (det er i øvrigt ikke mig selv der har lavet dll\'en)

Altså \"status := real_scauto_query(PChar(Id), PChar(Start), PChar(Opt), real_ev);\" leverer det forventede resultat.

status = korrekt sat lig med 0 (nul) og real_ev samt Event indeholder de forventede data.

Det er først ved \"scauto_query := status;\" fejlen opstår.
Avatar billede morten_s Nybegynder
05. januar 2002 - 13:41 #5
Jeg har ikke meget forstand på dll\'s men jeg gætter på at
det her er et IP nr \'10.0.0.100.12690\', og hvis det er så
er det ikke validt, et IP nr må maks være 255 på de forskellige pladser

altså \'10.0.0.100.255\'

status1 := scauto_connect(\'tkj\', \'10.0.0.100.12690\', \'mrtg\' , \'All\');
Avatar billede morten_s Nybegynder
05. januar 2002 - 13:43 #6
måske du mangler et : for port feks.

\'10.0.0.100.126:90\'
Avatar billede dkklein Nybegynder
05. januar 2002 - 13:43 #7
Du har gættet rigtigt, det er et ip nummer, men det sidste tal er skam også tilladt det er nemlig et portnummer og den eksterne dll forventer ip nummeret i det format. Så det er ikke det der er fejlen.
Avatar billede morten_s Nybegynder
05. januar 2002 - 13:45 #8
Ja men hvordan kan den vide hvad port det er ?

\'10.0.0.100.1:2690\' Valid
\'10.0.0.100.12:690\' Valid
\'10.0.0.100.126:90\' Valid
\'10.0.0.100.1269:0\' Ej valid ?
Avatar billede easysoft_studios Nybegynder
05. januar 2002 - 13:48 #9
dkklein >> så må du trace... det selvfølgelig lidt svært via en dll...

kan du køre koden fra selve programmet (exe) uden nogle fejl???

morten_s  >> EAccessViolation er den handling der udføres på en Access Violation.

Delphi Hjælp:

EAccessViolation is the exception class for invalid memory access errors

Unit

SysUtils

Description

EAccessViolation is raised when an application

Dereferences a nil pointer.
    Writes to memory reserved for executable code.
    Attempts to access a memory address for which there is no virtual memory allocated to the application.

Run-time exception information is saved in fields provided by EExternal.

Note:    Applications should not raise EAccessViolation directly, but should instead rely on the runtime to raise this exception.
Avatar billede dkklein Nybegynder
05. januar 2002 - 13:48 #10
Det er ikke ip/port nummer der er problemet. Jeg kunne også have skrevet
\'servernavn.portnummer\' ex \'minserver.12690\' ville være det samme. Et standard ip nummer består af 4 blokke tal mellem 0 og 255, hvad der måtte følge efter tolkes af den pågældende routine som et portnummer altså er det formatteret korrekt.
Avatar billede easysoft_studios Nybegynder
05. januar 2002 - 13:49 #11
Access Violation har altså ikke en skid med de ip\'er at gøre...
Avatar billede dkklein Nybegynder
05. januar 2002 - 13:50 #12
Jeg har tracet og ved derfor at fejlen opstår lige præcis i \"scauto_query := status;\" indtil det punkt er alt forløbet korrekt og som forventet.
Avatar billede dkklein Nybegynder
05. januar 2002 - 13:52 #13
Hvordan kan jeg bruge den debug information som windows er så flink at give mig når fejlen opstår?
Avatar billede dkklein Nybegynder
05. januar 2002 - 13:53 #14
Debug information fra windows ser således ud:

SCMRTG forårsagede en ugyldig sidefejl i
modul <ukendt> på adressen 0084:bff90777.
Indhold af registrene:
EAX=8631a044 CS=81dfa598 EIP=bff90777 EFLGS=bff741f7
EBX=85dbcb0c SS=bff7dafa ESP=85d34444 EBP=0063ff6c
ECX=bff741f7 DS=0040 ESI=00000008 FS=bff7a567
EDX=00000000 ES=81d07000 EDI=858329ac GS=bff7a10e
Byte ved CS:EIP:

Indhold af stakken:
Avatar billede easysoft_studios Nybegynder
05. januar 2002 - 13:55 #15
ja!

der er jeg lige nødt til at sidde med min Delphi...
jeg kikker på det.
Avatar billede easysoft_studios Nybegynder
05. januar 2002 - 19:20 #16
prøv at bruge result := status istedet for scauto_query := status.
Det er det samme, men blot deklareret på en anden måde...
Avatar billede dkklein Nybegynder
05. januar 2002 - 20:02 #17
Det hjalp ikke, jeg prøvede endda med result:=0

Avatar billede easysoft_studios Nybegynder
05. januar 2002 - 20:50 #18
stadig fejl???!!!!

så er der noget helt galt, med sendingen. prøv ud result := et-eller-andet, for at se om den stadig gør det, hvis ikke så prøv at smide result := på igen og kald functionen således:

function scauto_query(Id: string; Start: string; Opt: string; var Event: scauto_event) : Integer; stdcall;
var real_ev : real_scauto_event;
    status : Integer;
begin
    status := real_scauto_query(PChar(Id), PChar(Start), PChar(Opt), real_ev);
    if status = 0 then
        real_to_fake(real_ev, Event);
    scauto_query := status;
end;

hvis den stadig melder fejl, når du har fjernet result := så er det noget længere oppe i funcktionen der kuldre. Måske real_to_fake(), da den befinder  sig i exefilen - eller har jeg misforstået noget...?
Avatar billede dkklein Nybegynder
05. januar 2002 - 21:01 #19
Det hjalp heller ikke. Jeg vil nu prøve om jeg kan få flyttet de ting jeg skal bruge fra den eksterne unit ind i mit hovedprogram.
Avatar billede easysoft_studios Nybegynder
05. januar 2002 - 21:03 #20
jeg venter spændt :)
Avatar billede dkklein Nybegynder
05. januar 2002 - 21:15 #21
Det gjorde ingen forskel. Men nu har jeg konstateret at det må være returneringen af result den er gal med og altså heller ikke real_to_fake.

Når koden ser således ud:

function scauto_query(Id: string; Start: string; Opt: string; var Event: scauto_event) : Integer;
var real_ev : real_scauto_event;
    status : Integer;
begin
    status := real_scauto_query(PChar(Id), PChar(Start), PChar(Opt), real_ev);
    if status = 0 then
        real_to_fake(real_ev, Event);
    result := status;
end;

eller

function scauto_query(Id: string; Start: string; Opt: string; var Event: scauto_event) : Integer;
var real_ev : real_scauto_event;
    status : Integer;
begin
    status := real_scauto_query(PChar(Id), PChar(Start), PChar(Opt), real_ev);
    if status = 0 then
        real_to_fake(real_ev, Event);
    scauto_query := status;
end;

så fejler den, ser den derimod således ud

function scauto_query(Id: string; Start: string; Opt: string; var Event: scauto_event) : Integer;
var real_ev : real_scauto_event;
    status : Integer;
begin
    status := real_scauto_query(PChar(Id), PChar(Start), PChar(Opt), real_ev);
    if status = 0 then
        real_to_fake(real_ev, Event);
end;

Så fejler den ikke! Men det går bare ikke for jeg skal bruge retur koden til det videre program forløb.

Avatar billede easysoft_studios Nybegynder
05. januar 2002 - 21:19 #22
det er noget med at man skal lave et lille trick der fortæller programmet at den skal modtage variblen, status: integer;

jeg kan ikke huske hvordan, men jeg VED at det er derfor.
Avatar billede dkklein Nybegynder
05. januar 2002 - 21:37 #23
Damn det driller det her.

Jeg fik det lige til at virke ved at ændre functions kaldet til at status overgives som parameter i selv kaldet:

function scauto_query(Id: string; Start: string; Opt: string; var Event: scauto_event; var testtkj: Integer) : Integer;
var real_ev : real_scauto_event;
    status : Integer;
begin
    status := real_scauto_query(PChar(Id), PChar(Start), PChar(Opt), real_ev);
    if status = 0 then
        real_to_fake(real_ev, Event);
    testtkj:=status;
  (*  scauto_query := status;
    result := 0; *)
end;

Altså som variablen testtkj

Men så kørte jeg programmet 4-6 gange og fejlen var tilbage igen!!! Det fejler nu i testtkj:=status så jeg tror du har ret i det trick, men så er spørgsmålet hvor jeg finder det henne. Jeg har kigget lidt i bogen Mastering Deplhi 6 men ikke fundet så meget, har du en ide til hvor i delphi manualen jeg kan finde noget. Opslag i index på dll, external eller dynamic link  libraries giver intet.
Avatar billede easysoft_studios Nybegynder
05. januar 2002 - 22:11 #24
nu sidder jeg som sagt i et forkert OP (WinME) til at starte Delphi og hjælpe dig de vej. Men hvis du åbner den nørdede Delphi Hjælp og søger på noget i retingen af dll, dynamik library, calling functions etc. så kan den give dig en helt masse gode forslag.
Jeg vender lige tilbage med noget kode som jeg kom i tanke om netop nu...
Avatar billede easysoft_studios Nybegynder
05. januar 2002 - 23:48 #25
prøv lige at se hvad Delphi skriver til en når man laver en ny DLL:

Important note about DLL memory management: ShareMem must be the
  first unit in your library\'s USES clause AND your project\'s (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters.

har du overværet at putte ShareMem ind i dit exe-projekt??

det sådan set løsningen!
Avatar billede dkklein Nybegynder
06. januar 2002 - 08:47 #26
Der hjalp desværre heller ikke.
Avatar billede easysoft_studios Nybegynder
06. januar 2002 - 14:23 #27
hm...

kan du ikke sende HELE dit projekt til mig?

jhb@wl-cs.dk

Jeg kan ikke rigtig gennemskue det kode du har skrevet ovenfor.
Avatar billede dkklein Nybegynder
06. januar 2002 - 14:57 #28
Er sendt.
Avatar billede dkklein Nybegynder
06. januar 2002 - 18:59 #29
Point sat op da det ser ud til at være et svært problem.
Avatar billede dkklein Nybegynder
08. januar 2002 - 20:15 #30
Er der virklig ingen andre end easysoft_studios  der har nogen bud?
Avatar billede easysoft_studios Nybegynder
09. januar 2002 - 21:59 #31
post en ny, bare med et andet navn, og link her til...
men jeg er bange for den er svær, det er jo rent gætværk, for hverken dig, mig eller nogen anden på eksperten.dk kan vide hvad der står skrevet i den DLL... medmindre man har source eller er en dygtig hacker :)´

Som et allersidste forsøg, kan jeg kun refere til www.Experts-Exchange.com

der er måske nogle med det samme problem, som måske har en løsning.

Jeg er desværre løbet tør for ideer :(
Avatar billede dkklein Nybegynder
17. januar 2002 - 09:56 #32
jeg prøver at finde hjælp andet sted.
Avatar billede dkklein Nybegynder
30. januar 2002 - 17:46 #33
Mit problem er løst. Det viste sig at være scauto_event recorden der havde forkerte længder angivet på strings.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester