IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lazarus Pascal Discussion :

Erreur "Cannot access memory" : de brin !


Sujet :

Lazarus Pascal

  1. #1
    Membre confirmé
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2006
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 65
    Par défaut Erreur "Cannot access memory" : de brin !
    Bonjour à tous,

    J'ai un problème sur lequel je suis bloqué depuis 2 jours !

    Dans la fonction ci dessous, AAttrs est OK avant l'appel à la fonction SmartRcvDriveData, puis "Cannot access memory" après.

    J'ai changé le type de paramètre dans la déclaration de la fonction "out AAttrs: TSmartAttrs" et "var AAttrs: TSmartAttrs", ça fait rien.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    function SmartReadAttributeValues(const AHandle: THandle; const ADriveNumber: byte; out AAttrs: TSmartAttrs): boolean;
    var
       vInP:     TSendCmdInParams;
       vOutP:    TSendCmdOutParams;
       pAttrs,pAAttrs: PSmartAttrs;
       vB: boolean;
    begin
       pAAttrs:=@AAttrs; // pour debug
     
       // Dans points de suivi :
       // ici pAAttrs = psmartatts($00000000013FEA80)
       // ici AAttrs = record TSMARTATTRS {  A = 85,   B = 85,   RESULTS = {  {  ID = 85,  ......  85,   85,   85,   85},   RESERVED = 85} <repeats 30 times>},   RESERVED = {}}
     
       vB:=SmartRcvDriveData( AHandle,ADriveNumber,SMART_CMD,READ_ATTRIBUTES,1,1,
                                  SMART_CYL_LOW,SMART_CYL_HI,
                                  READ_ATTRIBUTE_BUFFER_SIZE,vOutP);
     
       // !!!! ici AAttrs = record TSMARTATTRS Cannot access memory at address 0x3209000000174181 POURQUOI?????
     
       if vB then begin
         pAttrs:=@vOutP.bBuffer;
         AAttrs:=pAttrs^;  //Erreur SIGSEG
       end;
       Result:=vB;
    end;
    Je vous mets le code de SmartRcvDriveData, au cas où...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    function SmartRcvDriveData( const AHandle: THandle; const ADriveNumber: byte;
                                const ACommand, AFeatures, ASecCount, ASecNum, ACylLow, ACylHigh: byte;
                                const ABufferSize: integer; out AOutParams: TSendCmdOutParams): TIOCTLResult;
    var
       vInP:      TSendCmdInParams;
       vRecBytes: dword;
    begin
       FillChar(vInP, Sizeof(TSendCmdInParams), 0);
     
       vInP.cBufferSize  := ABufferSize;
       vInP.bDriveNumber := ADriveNumber;
       vInP.irDriveRegs.bFeaturesReg := AFeatures;
       vInP.irDriveRegs.bSectorCountReg := ASecCount;
       vInP.irDriveRegs.bSectorNumberReg := ASecNum;
       vInP.irDriveRegs.bCylLowReg := ACylLow;   
       vInP.irDriveRegs.bCylHighReg := ACylHigh; 
       vInP.irDriveRegs.bDriveHeadReg := $A0 or ((ADriveNumber and 1) shl 4);    
       vInP.irDriveRegs.bCommandReg := ACommand;
     
       vRecBytes := 0;
       Result := DeviceIoControl(AHandle, SMART_RCV_DRIVE_DATA, @vInP, sizeof(vInP), @AOutParams, sizeof(AOutParams)+ABufferSize, vRecBytes, nil);
    end;
    Si vous avez une idée... Merci

  2. #2
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 937
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 937
    Par défaut
    out (comme var et const) est un paramètre passé par adresse dans le cas d'un paramètre typé, donc un pointeur.
    Pour contrôler l'adresse du paramètre en debug, ce sera plutôt pAAttrs := PSmartAttrs(AAttrs) ou pAAttrs := pointer(AAttrs). Mais ça n'a en soit pas grand intérêt.


    Maintenant si je me réfère à cette discussion, la déclaration de TSendCmdOutParams est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    TSendCmdOutParams = packed record
      cBufferSize  : DWORD;
      DriverStatus : TDriverStatus;
      bBuffer      : Array[0..0] of BYTE;
    end;
    Il faut comprendre ici que bBuffer est un tableau d'octets de longueur indéterminée (même si elle est connue et correspondant à READ_ATTRIBUTE_BUFFER_SIZE).

    En déclarant vOutP: TSendCmdOutParams, tu alloues un emplacement de seulement 1 double-mot + SizeOf(TDriverStatus) + 1 octet.
    Par la suite dans SmartRcvDriveData, tu veux y écrire SizeOf(AOutParams) +READ_ATTRIBUTE_BUFFER_SIZE. Il y a dépassement de capacité => violation d'accès.

    Il y a d'ailleurs ici aussi des erreurs. AOutParams comme expliqué précédemment est un pointeur (paramètre out), SizeOf(AOutParams) vaudra toujours 4 (en 32 bits), la taille d'un pointeur. C'est SizeOf(TSendCmdOutParams) +READ_ATTRIBUTE_BUFFER_SIZE -1 qu'il faut utiliser. Et toujours pour la même raison (out), DeviceIoControl(..., AOutParams, ...) sans le @.

    Tu as donc deux possibilités :

    soit tu modifies la déclaration :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    TSendCmdOutParams = packed record
      cBufferSize  : DWORD;
      DriverStatus : TDriverStatus;
      bBuffer      : Array[0..READ_ATTRIBUTE_BUFFER_SIZE -1] of BYTE;
    end;
    Soit tu travailles par pointeur et procède toi-même à l'allocation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    type
      PSendCmdOutParams = ^TSendCmdOutParams;
     
    var
      VOutP :PSendCmdOutParams;
     
    VOutP := GetMem(SizeOf(TSendCmdOutParams) +READ_ATTRIBUTE_BUFFER_SIZE -1);
    // et finir la procédure par FreeMem

    Enfin AAttrs:=pAttrs^ ne peut pas fonctionner puisque AAttrs est un pointeur, tu modifies l'adresse de AAttrs par le contenu de buffer. Tu dois au contraire copier le contenu : CopyMemory(AAttrs, @vOutP.bBuffer, READ_ATTRIBUTE_BUFFER_SIZE).

    Et même si AAttrs était une valeur, := ne fonctionnerait tout de même pas (compilation impossible) puisqu'il faudrait que les deux types soit parfaitement identiques, utilise le même type déclaré. Array[0..0] of BYTE n'est pas équivalent à TSmartAttrs quelque soit la déclaration de TSmartAttrs.


    Voilà, j'espère que ma réponse ne soulève pas plus de questions qu'elle n'en résout

  3. #3
    Membre confirmé
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2006
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 65
    Par défaut
    Salut et merci de m'avoir répondu.

    Ci dessous :
    (1) et (2) je réponds aux conseils donnés.
    (3) je présentes les Types que j'utilise, ça peut être utile, mais le problème ne viens pas de là.
    (4) J'expose le réel problème !

    Merci de prendre le temps de me lire ;-)

    (1) D'abord pour répondre au aux conseils concernant le transtypage :

    avec pAttrsDebug2: PSmartAttrs;
    J'obtiens les erreurs suivantes:

    pAttrsDebug2 := PSmartAttrs(AAttrs); Error: Illegal type conversion: "TSmartAttrs" to "PSmartAttrs"
    pAttrsDebug2 := pointer(AAttrs); Error: Illegal type conversion: "TSmartAttrs" to "Pointer"

    A noter que je compile en mode {$mode objfpc}{$H+}, peut être cela a t'il une influence ???

    (2) Sizeof

    vSize:=Sizeof(AOutParams); // = 17
    vSize:=Sizeof(TSendCmdOutParams); // = 17
    Mais c'est vrai que Sizeof(TSendCmdOutParams) c'est mieux.

    (3) Les types utilisés
    Les types et les constantes sont pour la plupart dans jwawinioctl.pas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
      _SENDCMDOUTPARAMS = packed record
        cBufferSize: DWORD;            // Size of bBuffer in bytes
        DriverStatus: DRIVERSTATUS;    // Driver status structure.
        bBuffer: array [0..0] of BYTE; // Buffer of arbitrary length in which to store the data read from the                                                                                  // drive.
      end;
      SENDCMDOUTPARAMS = _SENDCMDOUTPARAMS;
      TSendCmdOutParams = SENDCMDOUTPARAMS;
      PSendCmdOutParams = LPSENDCMDOUTPARAMS;
    Et pour les attributs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    TSmartAttrs = packed record
          A, B:     byte; // unknown
          Results:  array[0..29] of TSmartAttr; // max of 30 attributes
          Reserved: array[1..150] of byte; // to make it up to the right size
       end;
       PSmartAttrs = ^TSmartAttrs;
     
       TSmartAttr = packed record
          ID:    byte;
          Flags: word;
          Current, Worst: byte;
          Raw:   array[0..5] of byte; 
          Reserved: byte;
       end;

    (4) Le vrai problème:
    Le réel problème est : Pourquoi après l'appel a la fonction Windows DeviceIOcontrol, les variables passées en out ou var deviennent inaccessibles ?

    Dans le code ci dessous, j'arrive a récupérer exactement ce que je veux dans la variable locale vLocalAttrs, mais je ne peut pas l'attribuer a AAttrs, car depuis l'appel a DeviceIOControl cette variable n'est plus accessible (record TSMARTATTRS Cannot access memory at address 0x5c6400).
    Donc l'appel a la fonction DeviceIOControl se passe bien, elle me retourne bien ce que je veux a la bonne longueur.

    Encore Plus Tordu : Dans le code ci dessous j'ai ajouté une variable passé en var : ASertARien, qui ne sert a rien, juste a voir qu'elle aussi n'est plus accessible suite a l’appel de DeviceIOControl.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    function SmartReadAttributeValues2(const AHandle: THandle; const ADriveNumber: byte; var ASertARien: integer; var AAttrs: TSmartAttrs): boolean;
    var
       vOutP: TSendCmdOutParams;
       pAttrs,pAttrsDebug1: PSmartAttrs;
       vLocalAttrs : TSmartAttrs;
    begin
       pAttrsDebug1:=@AAttrs; //= psmartattrs($00000000013FEA80)
       ASertARien := 8888; //= 8888
       // ici AAttrs = record TSMARTATTRS {  A = 85,   B = 85,   RESULTS = {  {  ID = 85,   FLAGS = 21845,   CURRENT = 85,   WORST = 85,   RAW = {  85,   85,   85,   85,   85,   85},   RESERVED = 85} <repeats 30 times>},   RESERVED = {}}
     
       Result := SmartRcvDriveData2(AHandle, ADriveNumber, SMART_CMD, READ_ATTRIBUTES, 1, 1,
          SMART_CYL_LOW, SMART_CYL_HI,
          READ_ATTRIBUTE_BUFFER_SIZE, vOutP{%H-});
     
       // CATASTROPHE !
       // Ici ASertARien = Cannot access memory at address 0xde61610032040000
       // ici AAttrs = record TSMARTATTRS Cannot access memory at address 0x5c6400
     
       if Result then
       begin
          pAttrs := @vOutP.bBuffer;
          vLocalAttrs := pAttrs^; //ici vLocalAttrs contient exactement ce que je voudrais recuperer
          // Mais impossible de l'affecter à AAttrs car AAttrs est en "Cannot access memory"
          // depuis l'appel a DeviceIOControl
          AAttrs := vLocalAttrs;  //SIGSEG
       end;
       ASertARien:=555;
    end;
    J'ai inséré le code de la function SmartRcvDriveData2 dans cette procédure pour tester au cas ou... et méme probléme !!!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    function SmartReadAttributeValues3(const AHandle: THandle; const ADriveNumber: byte; var ASertARien: integer; var AAttrs: TSmartAttrs): boolean;
    var
       vOutP: TSendCmdOutParams;
       pAttrs,pAttrsDebug1: PSmartAttrs;
       vLocalAttrs : TSmartAttrs;
       vInP:      TSendCmdInParams;
       vRecBytes,ABufferSize: dword;
    begin
       pAttrsDebug1:=@AAttrs; //= psmartattrs($00000000013FEA80)
       ASertARien := 8888; //= 8888
       // ici AAttrs = record TSMARTATTRS {  A = 85,   B = 85,   RESULTS = {  {  ID = 85,   FLAGS = 21845,   CURRENT = 85,   WORST = 85,   RAW = {  85,   85,   85,   85,   85,   85},   RESERVED = 85} <repeats 30 times>},   RESERVED = {}}
     
       //Result := SmartRcvDriveData2(AHandle, ADriveNumber, SMART_CMD, READ_ATTRIBUTES, 1, 1,
       //   SMART_CYL_LOW, SMART_CYL_HI,
       //   READ_ATTRIBUTE_BUFFER_SIZE, vOutP{%H-});
     
       zeromemory(@vInP,Sizeof(TSendCmdInParams));
     
       ABufferSize:= READ_ATTRIBUTE_BUFFER_SIZE;
     
       vInP.cBufferSize  := ABufferSize;
       vInP.bDriveNumber := ADriveNumber;
       vInP.irDriveRegs.bFeaturesReg := READ_ATTRIBUTES; //AFeatures;
       vInP.irDriveRegs.bSectorCountReg := 1; //ASecCount;
       vInP.irDriveRegs.bSectorNumberReg := 1; //ASecNum;
       vInP.irDriveRegs.bCylLowReg := SMART_CYL_LOW; //ACylLow;
       vInP.irDriveRegs.bCylHighReg := SMART_CYL_HI; //ACylHigh;
       vInP.irDriveRegs.bDriveHeadReg := $A0 or ((ADriveNumber and 1) shl 4);
       vInP.irDriveRegs.bCommandReg := SMART_CMD; //ACommand;
     
       vRecBytes := 0;
       Result := DeviceIoControl(AHandle, SMART_RCV_DRIVE_DATA, @vInP, sizeof(vInP), @vOutP, sizeof(TSendCmdOutParams)+ABufferSize, vRecBytes, nil);
     
       // CATASTROPHE !
       // Ici ASertARien = Cannot access memory at address 0xde61610032040000
       // ici AAttrs = record TSMARTATTRS Cannot access memory at address 0x5c6400
     
       if Result then
       begin
          pAttrs := @vOutP.bBuffer;
          vLocalAttrs := pAttrs^; //ici vLocalAttrs contient exactement ce que je voudrais recuperer
          // Mais impossible de l'affecter à AAttrs car AAttrs est en "Cannot access memory"
          // depuis l'appel a DeviceIOControl
          AAttrs := vLocalAttrs;  //SIGSEG
       end;
       ASertARien:=555;
    end;

Discussions similaires

  1. Réponses: 0
    Dernier message: 31/03/2014, 13h09
  2. Cannot access memory
    Par kimikou dans le forum C
    Réponses: 2
    Dernier message: 19/04/2011, 08h53
  3. Erreur "Cannot access protected property"
    Par Bundy*Al dans le forum Langage
    Réponses: 4
    Dernier message: 04/12/2010, 18h14
  4. [SIGBUS] Cannot Access Memory apres un Malloc?
    Par predacktor dans le forum C
    Réponses: 5
    Dernier message: 18/03/2006, 17h11
  5. [CR7] Erreur CanNot initalize OLE
    Par elifqaoui dans le forum SAP Crystal Reports
    Réponses: 4
    Dernier message: 17/07/2003, 22h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo