2013-02-05 3 views
2

J'essaie de lire la mémoire via ReadProcessMemory(), puis de stocker la valeur lue dans un float (c'est certainement un flottant en mémoire, je l'ai vérifié avec un autre utilitaire) pour référence ultérieure, mais tout ce que j'ai essayé (BitConverter, Marshal.Copy(), etc.) semble échouer.C#: violation d'accès Marshal.Copy() conversion de IntPtr à float

J'ai regardé un certain nombre d'exemples et je ne suis pas sûr de ce que je n'arrive pas à comprendre.

J'ai fait un petit programme pour tester le concept. Je connais d'autres techniques pour accomplir cette tâche, mais j'ai aussi des problèmes avec eux, alors je me concentre sur ce point maintenant. Fondamentalement, je stocke (connu) octets d'une valeur flottante dans un tableau de 4 octets, pointez via un IntPtr, puis utilisez Marshal.Copy() pour essayer de convertir IntPtr à un flotteur:

const int FLOAT_SIZE = 4; 
byte[] baSource = new byte[FLOAT_SIZE]; 
IntPtr ipIntermediate = Marshal.AllocHGlobal(sizeof(float)); 
float[] faDest = new float[1]; 

baSource[0] = 0xA7; 
baSource[1] = 0x68; 
baSource[2] = 0xB9; 
baSource[3] = 0x44; 

ipIntermediate = ((IntPtr)(baSource[0])); 
Marshal.Copy(ipIntermediate, faDest, 0, 1); // causes AccessViolation exception 

Je cours Windows 7 64 bits. Je cible actuellement cette version pour x86, mais j'ai aussi essayé 'Any CPU' pour obtenir le même résultat. L'endianness ne semble pas non plus être le problème.

Toute aide serait grandement appréciée.

Répondre

2

((IntPtr)(baSource[0])) signifie: prendre premier élément de tableau, et le convertir en IntPtr. Ce que vous voulez réellement: obtenir une adresse du premier élément du tableau d'octets. Vous pouvez utiliser le code dangereux ou GCHandle pour y parvenir:

const int FLOAT_SIZE = 4; 
byte[] baSource = new byte[FLOAT_SIZE]; 
float[] faDest = new float[1]; 

baSource[0] = 0xA7; 
baSource[1] = 0x68; 
baSource[2] = 0xB9; 
baSource[3] = 0x44; 

var gch = GCHandle.Alloc(baSource, GCHandleType.Pinned); 
try 
{ 
    var source = gch.AddrOfPinnedObject(); 
    Marshal.Copy(source, faDest, 0, 1); 
} 
finally 
{ 
    gch.Free(); 
} 
+0

Merci, j'ai complètement oublié d'épingler les données. Je ne l'ai pas essayé (j'ai cassé et utilisé BitConverter.ToSingle()) mais il semble que cela devrait fonctionner. –

0

Probablement parce que IntPtr est un pointeur, il est interprété comme un pointeur, pas comme une donnée, dans votre appel à Marshal.Copy.

Notez qu'il ya un moyen beaucoup plus simple de construire un flotteur de ses octets constitutifs:

float f2 = BitConverter.ToSingle(byteArray, 0); 
+0

J'utilise cette surcharge: http://msdn.microsoft.com/en-us/library/a53bd6cz.aspx ... est-il pas destiné pour cet usage? –

+0

Oui, un peu, mais il s'attend à ce que le premier argument, ipIntermediate, soit un pointeur vers les octets, pas les octets eux-mêmes. –

+0

Cela ne répond pas réellement à la question. – Odrade