![]() |
[AV] Ende einer Prozedur verursacht eine AV...
Liste der Anhänge anzeigen (Anzahl: 1)
N'Abend,
Ich hab' mal wieder ein kleines Problem mit einem C - Code, den ich nach Delphi portiert habe. (Ja, ich weiß, ich sollte diese verdammte Sprache endlich lernen :wall: ). Da in dem Original die AV nicht auftritt, denke ich, dass das mit meiner Portierung zu tun hat... Nevertheless, mein Problem liegt hier:
Delphi-Quellcode:
Nachdem die Funktion durchlaufen wurde, werde ich mit einer AV bombadiert:
//----------------------------------------------------------------------------
// ATA-Befehle unter Windows 2000 oder XP versenden Function TAAMClass.SendCommand_Win2000(pATARegs: PATARegs; var pBuf; BufSize: Cardinal; pResultSize: Cardinal): Boolean; var Size: Cardinal; VirtualAddress: Pointer; pAPT: ATA_PASS_THROUGH; BytesReturned: LongWord; Status: Boolean; ReturnedSize: Cardinal; begin Result := FALSE; BytesReturned := 0; Size := sizeof(ATA_PASS_THROUGH) + BufSize; // Datenpuffer mit VirtualAlloc anfordern, damit der Gerätetreiber den Speicher ansprechen kann VirtualAddress := VirtualAlloc(NIL, Size, MEM_COMMIT, PAGE_READWRITE); pAPT := ATA_PASS_THROUGH(VirtualAddress^); if Assigned(@pAPT) then begin //ZeroMemory(@pAPT, Size); // Größe des Datenpuffers setzen pAPT.DataBufferSize := BufSize; // ATA-Register setzen pAPT.IdeReg.bFeaturesReg := pATARegs^.Reg[0]; pAPT.IdeReg.bSectorCountReg := pATARegs^.Reg[1]; pAPT.IdeReg.bSectorNumberReg := pATARegs^.Reg[2]; pAPT.IdeReg.bCylLowReg := pATARegs^.Reg[3]; pAPT.IdeReg.bCylHighReg := pATARegs^.Reg[4]; pAPT.IdeReg.bDriveHeadReg := pATARegs^.Reg[5]; pAPT.IdeReg.bCommandReg := pATARegs^.Reg[6]; if (pAPT.IdeReg.bCommandReg = $EC) then // ist es ATA IDENTIFY? begin // Windows XP merkt sich den IDE-Konfigurationssektor // daher vorher mit IOCTL_SCSI_RESCAN_BUS für ungültig erklären DeviceIoControl(fDriveHandle, IOCTL_SCSI_RESCAN_BUS, NIL, 0, NIL, 0, BytesReturned, 0); // eine halbe Sekunde warten Sleep(500); end; BytesReturned := 0; Status := DeviceIoControl(fDriveHandle, IOCTL_IDE_PASS_THROUGH, @pAPT, Size, @pAPT, Size, BytesReturned, 0); if not Status then fError := aec_CommandFailed else begin if Assigned(@pBuf) then begin if (BufSize <> 0) then ZeroMemory(@pBuf, BufSize); if (BytesReturned > sizeof(ATA_PASS_THROUGH)) then begin ReturnedSize := BytesReturned - sizeof(ATA_PASS_THROUGH); if (pResultSize <> 0) then pResultSize := ReturnedSize; if (ReturnedSize > BufSize) then ReturnedSize := BufSize; Move(pAPT.DataBuffer, pBuf, ReturnedSize); end; end; Result := TRUE; end; VirtualFree(@pAPT, Size, MEM_RELEASE); end else fError := aec_OutOfMemory; end; Zitat:
Der äquivalente C - Code wäre:
Code:
Hat irgendwer eine Idee? Im Anhang ist mal das komplette Delphi - Projekt. Auf das C - Original verlinke ich lieber. Ist von der c't... es handelt sich um die "WinATA.cpp".
//----------------------------------------------------------------------------
// ATA-Befehle unter Windows 2000 oder XP versenden BOOL CWinAta::SendCommand_Win2000(PATARegs pATARegs, void *pBuf, unsigned int BufSize, unsigned int *pResultSize) { //--------------------------------------------------- // Definitionen und Datenstruktur für Windows 2000 und XP // aus dem DDK-Headerfile ntddscsi.h übernommen #define IOCTL_IDE_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x040A, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) #define FILE_ANY_ACCESS 0 #define IOCTL_SCSI_RESCAN_BUS CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS) typedef struct { IDEREGS IdeReg; ULONG DataBufferSize; UCHAR DataBuffer[1]; } ATA_PASS_THROUGH; //--------------------------------------------------- BOOL Result = FALSE; unsigned int Size = sizeof(ATA_PASS_THROUGH) + BufSize; // Datenpuffer mit VirtualAlloc anfordern, damit der Gerätetreiber den Speicher ansprechen kann ATA_PASS_THROUGH *pAPT = (ATA_PASS_THROUGH *)VirtualAlloc(NULL, Size, MEM_COMMIT, PAGE_READWRITE); if (pAPT) { memset(pAPT, 0, Size); // Größe des Datenpuffers setzen pAPT->DataBufferSize = BufSize; // ATA-Register setzen pAPT->IdeReg.bFeaturesReg = pATARegs->Reg[0]; pAPT->IdeReg.bSectorCountReg = pATARegs->Reg[1]; pAPT->IdeReg.bSectorNumberReg = pATARegs->Reg[2]; pAPT->IdeReg.bCylLowReg = pATARegs->Reg[3]; pAPT->IdeReg.bCylHighReg = pATARegs->Reg[4]; pAPT->IdeReg.bDriveHeadReg = pATARegs->Reg[5]; pAPT->IdeReg.bCommandReg = pATARegs->Reg[6]; if (pAPT->IdeReg.bCommandReg == 0xEC) // ist es ATA IDENTIFY? { // Windows XP merkt sich den IDE-Konfigurationssektor // daher vorher mit IOCTL_SCSI_RESCAN_BUS für ungültig erklären DWORD BytesReturned = 0; (void)DeviceIoControl(Device, IOCTL_SCSI_RESCAN_BUS, NULL, 0, NULL, 0, &BytesReturned, FALSE); // eine halbe Sekunde warten Sleep(500); } DWORD BytesReturned = 0; BOOL Status = DeviceIoControl(Device, IOCTL_IDE_PASS_THROUGH, pAPT, Size, pAPT, Size, &BytesReturned, FALSE); if (!Status) WinAtaErrorCode = aec_CommandFailed; else { if (pBuf) { if (BufSize) memset(pBuf, 0, BufSize); if (BytesReturned > sizeof(ATA_PASS_THROUGH)) { unsigned int ReturnedSize = BytesReturned - sizeof(ATA_PASS_THROUGH); if (pResultSize) *pResultSize = ReturnedSize; if (ReturnedSize > BufSize) ReturnedSize = BufSize; memcpy(pBuf, pAPT->DataBuffer, ReturnedSize); } } Result = TRUE; } VirtualFree(pAPT, Size, MEM_RELEASE); } else WinAtaErrorCode = aec_OutOfMemory; return Result; } ![]() Danke schonmal für's lesen. ;) |
Re: [AV] Ende einer Prozedur verursacht eine AV...
So, ich bins wieder. Ich habe mir das CPU - Fenster mal genauer angesehen. Es hängt also wirklich mit irgendeinem falsch zeigenden Pointer zusammen. So sehen ich in dem Fenster, wo die ganzen Adressen stehen, lauter Fragezeichen.
Kann es eventuell an einer falschen Verwendung von VirtualAlloc liegen? |
Re: [AV] Ende einer Prozedur verursacht eine AV...
Oder an MemSet() und MemCopy()?. Wie wärs denn mit was debugbarem, wenn du es nicht hinbekommst die Adressen zu debuggen...
|
Re: [AV] Ende einer Prozedur verursacht eine AV...
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
//Edit: Ich bin gerade auf die großartige Idee gekommen, dass ich die MadExcept ja wieder installieren könnte. :mrgreen: Ich hol das mal eben nach... //Edit2: So, hier mal der Bugreport. Das Projekt selbst befindet sich ja oben im Anhang |
Re: [AV] Ende einer Prozedur verursacht eine AV...
Zitat:
|
Re: [AV] Ende einer Prozedur verursacht eine AV...
Code:
Das bedeutet, dass pAPT ein ZEIGER auf eine ATA_PASS_THROUGH-Struktur ist.
ATA_PASS_THROUGH *pAPT
Nachdem du das in Delphi geändert hast, kannst du den Typecast und die @'s vor pAPT entfernen (Assigned(@x) ist 'ne ziemlich sinnlose Abfrage). |
Re: [AV] Ende einer Prozedur verursacht eine AV...
Hi Flocke,
das heißt also, wenn ich
Delphi-Quellcode:
definieren würde, könnte ich das so schreiben:
Type
PATA_PASS_THROUGH = ^ATA_PASS_THROUGH
Delphi-Quellcode:
Damit wäre ich diese AV schonmal interessanterweise los. Vllt. is' das ja doch nicht so kompliziert, wie ich denke... Aber warum ist "Assigned(@pAPT)" mit der alten Definition denn sinnlos?
var
pAPT: PATA_PASS_THROUGH; begin pAPT := VirtualAlloc(NIL, Size, MEM_COMMIT, PAGE_READWRITE); if Assigned(pAPT) then [...] |
Re: [AV] Ende einer Prozedur verursacht eine AV...
Moin Daniel,
Zitat:
Assigned prüft den Ausdruck auf nil. Nun wird die Adresse einer Variablen aber wohl nie gleich nil sein... ;-) |
Re: [AV] Ende einer Prozedur verursacht eine AV...
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:44 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz