Mémoire ne peut pas être "Read" ==> causes possibles ?

violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 - 12 nov. 2006 à 19:53
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 - 20 nov. 2006 à 20:49
Violent Ken

Bonjour, j'ai compilé mon application, et j'obtiens le célèbre bug "l'instruction à "0x00000000" emploie l'adresse mémoire "0x00000000". La mémoire ne peut pas être "read""

Ce bug arrive toujours au même endroit, après une certaine suite d'actions dans mon programme.

Quelles peut être la cause de ce bug ?
Comment puis-je debuger mon programme ?

Je vous demande pas de le debuger, juste me dire le causes principales de ce genre de truc ;)

Merci, @+

60 réponses

violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
13 nov. 2006 à 23:50
Violent Ken

Content que çà marche chez toi ^^ (moi aussi c'est OK pour çà)

"Après recherche sur MSDN on en déduit que l'Api  SetFilePointerEx est inutile  car on travaille avec une structure Overlapped  qui contient le pointeur d'octets à lire ou à écrire" ==> Hum, intéressant. Je vais me pencher dessus demain ^_^

"ShareVb tu peux en dire plus sur l'échelle 10000 de Currency : je vais chercher de mon côté" ==> Moi j'avais compris qu'il parlait du fait qu'une valeur en Currency peut être décimale (si on stocke dedans une LARGE_INTEGER qui dépasse la valeur max entière ?), et comme on travaille sur des adresses, il faut bien sur du entier. Mais les valeurs ne passent jamais décimales (car trop petites), donc pas de gestion particulière de ces cas.
Ou alors j'ai pas compris ?

En tout cas merci encore, bonne nuit.
@+
0
Profil bloqué
13 nov. 2006 à 23:54
Au sujet de SetFilePointerEx je l'avais mis en currency car il pointe les octets du disque dur et un 20 Go cela fait 20 000 000 000 et cela dépasse les limites d'un Long ( de - 2 147 483 648 à + 2 147 483 647 signé bien sûr). Mais vu que maintenant il est inutile ( voir mon précédent post)

Alez salut les gars

GRENIER Alain[8D]
0
Profil bloqué
13 nov. 2006 à 23:57
Pour Violent_Ken

je confirme : SetFile PointerEx est inutile et cela fonctionne très bien

Salut

GRENIER Alain[8D]
0
Profil bloqué
14 nov. 2006 à 00:02
C'est encore moi
Pour le type currency tapez currency dans la recherche des codes et vous trouverez un tutoriel très bien fait qui explique les raisons de ce type de variable

GRENIER Alain[8D]
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
14 nov. 2006 à 09:08
salut,

le type currency est un type qui est entier EN INTERNE mais qui à une précision de 4 chiffres à près la virgule. Currency n'est pas un format float...

autrement si tu veux avoir 1024 comme entier dans le currency, il faudra écrire 0.1024...donc divisé par 10000...

par exemple :
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

Private Sub Form_Load()
Dim c As Currency
Dim l As Long
c = 0.1024

CopyMemory l, c, 4
End Sub

ShareVB
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
14 nov. 2006 à 11:46
Violent Ken
Galain ==> Je vais essayer ce soir, dès que j'aurais accès à mon PC, de supprimer les lignes correspondant à l'utilisation de SetFilePointerEx.
"on en déduit que l'Api  SetFilePointerEx est inutile  car on travaille
avec une structure Overlapped  qui contient le pointeur d'octets à lire
ou à écrire"
Ok, donc on renseigne sur le Currency de début d'offset dans le LARGE_INTEGER contenu dans la structure OVERLAPPED (OffsetHigh et Offset).

ShareVB ==> "autrement si tu veux avoir 1024 comme entier dans le currency, il faudra écrire 0.1024...donc divisé par 10000..."Hum, mais pourquoi "tOver.Offset CLng(crPointeur): tOver.OffsetHigh CLng(crHi32)" fonctionne avec crPointeur entier ?

Je veux dire qu'il me semble que si on fait :
Dim curVariable As Currency
Dim lngVariable As Long
    curVariable=1024
    lngVariable=Clng(curVariable)
    Msgbox Cstr(lngVariable)
on obtiendra "1024", car Clng aura convertit la partie entière (car inférieure à 2147483 647) de la variable Currency en Long.

Autrement dit, je pense que :
Dim lngVariable As Long

    curVariable=548.252

    lngVariable=Clng(curVariable)

    Msgbox Cstr(lngVariable)
renverra "548".

Je me trompe ? (j'ai pas VB d'installé sur la machine pour vérifier)
Si c'était le cas, il n'est pas nécessaire d'appliquer un quelconque coefficient multiplicateur de 10^4, car je ne travaille qu'avec des valeurs entières, et inférieures à la plage maximale entière que m'offre le type Currency.

@+
0
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
14 nov. 2006 à 12:11
salut,

effectivement, je parle du point de vue CopyMemory et représentation interne...donc principalement pour SetFilePointerEx...le 10000 c'est juste pour l'utilisation dans un paramètre d'API...

donc en fait, ca marche pour ton overlapped vu que tu fais du calcul en vb mais pour setfilepointerex vu que tu passes directement la currency sans conversion, donc la représentation interne, tu vas te placer 10000 fois trop loin dans le fichier...ca vient donc peut être de là...

ShareVB
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
14 nov. 2006 à 13:22
Violent Ken
"donc en fait, ca marche pour ton overlapped vu que tu fais du calcul en
vb mais pour setfilepointerex vu que tu passes directement la currency
sans conversion, donc la représentation interne, tu vas te placer 10000
fois trop loin dans le fichier"
> Hum, il va falloir que je vérifie çà, c'est effectivement probable. Mais de toutes façons, Galain a réussi a utiliser sa procedure de lecture sur le disque (celle que j'ai codée et qui pose problème est directement inspirée de la sienne) sans cette API. Donc je dois pouvoir faire sans.

"...ca vient donc peut être de là..." ==> Je ne pense pas ; j'ai pas encore terminé diskFrm (qui ouvre le disque en hexa), et donc pour l'instant, seul le premier secteur du disque dur est "affiché correctement" (les autres sotn décalés...etc.). Donc même si il y a un coefficient 10^4 en trop, çà ne devrait pas générer de problème (puisque je me contente de lire le premier secteur quand je teste mon *.exe compilé)
Mais par contre, j'ai une erreur quand je navigue dans mon disque (genre dépassement de capacité) sur les autres secteurs, et là c'est très certainement dû à çà.
Je vais vérifier ce soir.
Merci, @+
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
14 nov. 2006 à 20:21
Violent Ken

Bonsoir !

Alors j'ai étudié l'intérêt de SetFilePointerEx, j'ai vu qu'il était dispensable, mais j'ai surtout vu que le bug ne venait pas de là, mais venait très précisément de :

ReadFileEx lDrive, ByVal VarPtr(lResult(0)), lLen, tOver, 0&
(ou bien la version antérieure sans le VarPtr)

Alors comme je voyais pas l'erreur contenue dans cette ligne de code, j'ai décidé de changer cette sub complètement... je me suis inspiré de http://vbcity.com/forums/faq.asp?fid=9&cat=System#TID6975 , et j'ai opté pour des APIs utilisés pour des actions non asynchrones (donc SetFilePointer et ReadFile) parce que... je vois pas l'utilité du -Ex ;)

Donc çà donne çà :

Public Sub DirectReadDriveNT(ByVal sDrive As String, ByVal iStartSec As Currency, ByVal iOffset As Currency, ByVal cBytes As Long, ByVal BytesPerSector As Long, ByRef abResult() As Byte)
Dim hDevice As Long
Dim abBuff() As Byte
Dim nSectors As Currency
Dim nRead As Long


    'obtient un path valide pour l'API CreateFIle si nécessaire
    If Len(sDrive) <> 6 Then sDrive = BuildDrive(sDrive)


    'calcule le numéro du secteur lu
    nSectors = Int((iOffset + cBytes - 1) / BytesPerSector) + 1
   
    'ouvre le drive
    hDevice = CreateFile(sDrive, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, 0&, 0&)
   
    'quitte si le handle n'est pas valide
    If hDevice = INVALID_HANDLE_VALUE Then Exit Sub
   
    'move pointer
    Call SetFilePointer(hDevice, iStartSec * BytesPerSector, 0, FILE_BEGIN)
   
    'redimensionne les tableaux résultants
    ReDim abResult(cBytes - 1)
    ReDim abBuff(nSectors * BytesPerSector - 1)
   
    'appel l'API de lecture
    Call ReadFile(hDevice, abBuff(0), UBound(abBuff) + 1, nRead, 0&)
   
    'ferme le handle
    CloseHandle hDevice
   
    'stocke le résultat dans le tableau
    CopyMemory abResult(0), abBuff(iOffset), cBytes
End Sub

et çà marche a priori !

Certes, il y a un bug pour certaines valeurs de l'Offset ("L'exception résultat inexact en virgule flottante. (0xc000008f s'est produite dans l'application à l'emplacement 0x7c812a5b"). C'est très certainement dû au problème soulevé par ShareVB sur le type Currency.
Ou alors il manque un Clng, Ccur ou quelque chose comme çà.

La procédure en elle même est moins performante que celle proche de celle de Galain, mais je vais tenter d'optimiser çà.

Concernant le bug du freeze de la fenêtre Ouvrir (Common Dialog Control) pour le path "Poste de travail", c'est reglé !

Pour le bug "La mémoire ne peut être "Read"...", c'est a priori réglé pour le moment !

Pour le bug sur les MDIForm, çà persiste quand même (dammit !!)
Voilà le résultat, après ouverture de diskFrm, puis d'une autre form (par exemple édition de fichier) 
http://www.enregistrersous.com/images/52b30614e3be9b557ceeb84209d601e6.jpg
mais c'est sans doutes un autre problème, complètement indépendant de celui résolu.

Donc je peux désormais dire que le problème de  "mémoire ne peut etre "Read"..." EST RESOLU !!
Tout n'est pas parfait, mais cette erreur que je ne m'expliquais pas a disparu, c'était un problème généré par la procédure ReadDiskBytes (API ReadFileEx).

> MERCI à tous ceux qui m'ont répondu, pour leur patience, leur disponiblité et leurs connaissances (en particulier MERCI à Galain et ShareVB).
J'y serais jamais arrivé sans vous, vous êtes trop fort les gars ;)

Encore merci, @+
Bonne prog !
0
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
14 nov. 2006 à 20:38
salut,

juste pour l'histoire de compléter : franchement je me demande pourquoi j'ai pas regarder readfileex de près avant : le dernier paramètre ne doit pas être nul vu que c'est la fonction qui est appelée lorsque la lecture est terminée...de plus, vb n'aime pas bien le multi accès dans le code...

pour ce qui de l'exception machin truc : si tu passes directement un currency dans une api alors tu dois diviser la valeur par 10000 OBLIGATOIREMENT...

ShareVB
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
14 nov. 2006 à 20:53
Violent Ken

"si tu passes directement un currency dans une api alors tu dois diviser la valeur par 10000 OBLIGATOIREMENT" ==> Oui, oui, tout à fait.

"juste pour l'histoire de compléter : franchement je me demande pourquoi j'ai pas regarder readfileex de près avant : le dernier paramètre ne doit pas être nul vu que c'est la fonction qui est appelée lorsque la lecture est terminée"
> Disons que les codes utilisant cette API que j'ai rencontrés (notemment celui de Galain) marchent bien, et avec le dernier paramère nul. D'ou le fait que je n'ai rien précise dans ce paramètre.

J'ai mis un AddressOf(function_inutile) qui résout complètement le problème.

Merci encore, @+
0
Profil bloqué
14 nov. 2006 à 21:31
Salut ShareVb et Violent_Ken

Permettez moi de reprendre l'histoire de ma fonction pour lire les secteurs de disques durs

1° CreateFile,SetFilePointer et Readfile : mais on ne lit que les 2 premiers Go du disque dur ou de la partition
2° CreateFile,SetFilePointerEx et ReadFileEx et là plus de limite
3° SetFilePointer est inutile ( c'était hier)

Le dernier paramètre de ReadFileEx est l'adresse d'une fonction qui est appelée une fois le ReadFileEx appelée si la valeur de ce paramètre est différent de 0.si on met à 0 aucun appel de fonction est réalisé.
Le code devrait fonctionner aussi bien avec Readfile qu'avec ReadfileEx car le pointeur d'octets est contenu dans la structure Overlapped

il n'y a aucun problème avec les currency car on ne fait que des calculs sur ce type de valeur et on ne copie rien en mémoire. Par contre j'avais fait une erreur  en passant un Cuurrency avec SetFilePointerEx ( voir la division par 10000 ) mais cette erreur n'est jamais apparue car SetFilePointerEx était inutile.

donc Violent_Ken chez moi mon code fonctionne et j'espère qu'il fonctionne correctement chez toi.Teste ta fonction en affichant le secteur 39 000 000 si ta partition est > à 20 Go et si c'est Ok tu as gagné

bonne prog à vous deux et merci pour vos conseils

vive codes-Sources
GRENIER Alain[8D]
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
14 nov. 2006 à 21:49
Violent Ken

Salut Galain,

le problème est que la procédure ReadDiskByte en elle-même (même erronnée) fonctionne correctement. Mais elle génère ailleurs (chez moi au loading d'une autre Form) une erreur d'accès à la mémoire.

Et c'est complètement justifié.

Remplace dans ton progamme la ligne de code du ReadFileEx par
result& = ReadFileEx(hDevice&, readoctet(0), nbytes&, over, AddressOf CallBackREADFILE)

et créé dessous cette fonction :

Private Function CallBackREADFILE()
Beep
End Function

Ton programme fera "beep" quand la fonction CallBackREADFILE sera appelée par l'API ReadFileEx.
Dans ton cas, je pense que ton application ne fera jamais "beep" (sinon tu aurais eu la même erreur que moi à l'endroit ou le "beep" se fait entendre).

Dans mon cas, le "beep" apparait au loading de frmProcesses.
Et c'est exactement au même endroit que mon bug apparaissait.
Explication logique : ReadFileEx avait comme paramètre un pointeur nul (pas de fonction mais 0&) ==> bug, accès vers une zone mémoire impossible.

Donc ne pas spécifier de pointeur vers une fonction est une erreur de programmation, bien que le bug résultant ne soit (apparement) pas toujours visible (si CallBackREADFILE n'est jamais appellée)
MSDN ne précise pas que le dernier paramètre puisse être 0& ; donc il FAUT préciser une long qui pointe vers un truc valide.

"1° CreateFile,SetFilePointer et Readfile : mais on ne lit que les 2 premiers Go du disque dur ou de la partition
2° CreateFile,SetFilePointerEx et ReadFileEx et là plus de limite"
> Je pense qu'en changeant les déclarations des APIs SetFilePointer, ReadFile...de Long vers Currency, la limite disparait.
La différence entre ReadFile et ReadFileEx, SetFilePointer et SetFilePointerEx est le fait que LaFonctionEx est utilisé pour des actions asynchrones (contrairement à LaFonction)

"il n'y a aucun problème avec les currency car on ne fait que des calculs sur ce type de valeur et on ne copie rien en mémoire."
> Dans la nouvelle procédure que j'ai postée, j'uilise un CopyMemory : c'est la qu'il faut diviser par 10^4.
Mais dans ton code, oui, pas de problème de Currency.

Merci encore, @+
(corrigez moi si je dis des trucs faux ;))
0
Profil bloqué
14 nov. 2006 à 21:52
Pour Violent_Ken

Je suis désolé de t'informer que tu n'auras accès au 2 premiers Go de tes partitions car le code dont tu t'es inspiré sur le site VBcity est le code qui m'a permis de faire "Accès direct disque" à ses premiers débuts et j'ai été confronté à la limite des 2 Go ( valeur maxi d'un Long signée).
C'est là que je me suis tourné vers SetFilePointerEx et ReadFileEx qui prenne en charge des capacités bien supérieures ( jusqu'a 4 To soit 4096 gigaoctets) et les structures Overlapped et la gymnastique pour avoir les 2 valeurs Overlapped en Long signées

dis-moi ce qu'il en est de tes accès partitions si tu dépasses la limite des 2 Go : normalement ça doit planter ou générer un message d'erreur

GRENIER Alain[8D]
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
14 nov. 2006 à 22:00
Violent Ken

Pour mes accès partition, je n'ai pas testé, mon programme n'est pas encore opérationnel pour visualiser les secteurs autres que le premier.

Mais regarde ceci
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/readfile.asp
la différence entre là :
"The ReadFile function reads data from a file, and starts at the position that the file pointer indicates. You can use this function for both synchronous and asynchronous operations.


The ReadFileEx function is for only asynchronous operation."

Donc si l'on utilise correctement la stucture OVERLAPPED avec ReadFile, çà devrait très bien passer pour des disques de plus de2Go, tout comme avec ReadFileEx.
Les 2 APIs sont identiques à ce niveau.

"Je suis désolé de t'informer que tu n'auras accès au 2 premiers Go de tes partitions car le code dont tu t'es inspiré sur le site VBcity est le code qui m'a permis de faire "Accès direct disque" à ses premiers débuts et j'ai été confronté à la limite des 2 Go "
> Tout à fait, car il n'utilisent pas la structure OVERLAPPED, et parce qu'ils se limitent à des Long.

C'est çà qui est incorrect
"Private DeclareFunction ReadFile Lib"kernel32" (ByVal hFile AsLong, lpBuffer AsAny, ByVal nNumberOfBytesToRead AsLong, lpNumberOfBytesRead AsLong, ByVal lpOverlapped AsLong) AsLong "
Mais çà se change pour s'adapter au Currency sans problèmes je pense.

@+
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
14 nov. 2006 à 22:09
Violent Ken

"Le dernier paramètre de ReadFileEx est l'adresse d'une fonction qui est appelée une fois le ReadFileEx appelée si la valeur de ce paramètre est différent de 0.si on met à 0 aucun appel de fonction est réalisé."

> C'est là le problème.
"lpCompletionRoutine
[in] Pointer to the completion routine to be called when the read operation is complete and the calling thread is in an alertable wait state. For more information about the completion routine, see FileIOCompletionRoutine."
0 n'est pas autorisé, il faut préciser une adresse de fonction : quand 0 est autorisé, MSDN le précise (là c'est pas le cas).

@+
0
Profil bloqué
14 nov. 2006 à 22:30
Salut Violent_Ken

J'ai mis les routines de CallBack en AdressOf pour mes accès disque : comme tu le prévoyais chez moi cela ne fait pas Beep.
Merci pour ta patience et ton aide car j'en ai appris pas mal grâce à toi et à ShareVb : comme on dit il faut savoir partager et partager son savoir

A+ et bonne prog ( j'ai vu l'aperçu de ton programme grâce à l'image que tu as mis : cela déchire). Bravo

GRENIER Alain[8D]
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
14 nov. 2006 à 22:46
Violent Ken

Merci à toi pour ta patience et tes connaissances partagées.
Ce topic fut long, mais enrichissant ;)

Et merci pour le compliment ^^

Bonne soirée, @+
0
le cancre Messages postés 292 Date d'inscription mercredi 25 octobre 2006 Statut Membre Dernière intervention 27 novembre 2009
20 nov. 2006 à 20:25
salut violent ken,
j'ai eu le meme code erreur que toi...je sais pas si tu as solutionner ton probleme ou pas

pour moi cas, c'est une faute de frappe <--chose qui arrive souvent
j'ai utilisé copymemory avec le mauvais nom de ma structure,donc une structure vide qui n'existe pas d'ou cette adresse 00000000000

voila à plus
0
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
20 nov. 2006 à 20:49
Violent Ken

Salut, j'ai effectivement solutionné le problème et c'était vraiment du même ordre ==> argument qui réclamait une adresse de fonction de CallBack et j'avais passé 0&...

Merci, @+ et bonne prog. ^^
0
Rejoignez-nous