Question

J'ai essayé de construire une bibliothèque de lecture de mémoire très minimalistes pour lire quelques unsigned ints hors de lui. Cependant, je lance dans un message d'erreur « HEAP CORRUPTION DETECTEE » lorsque la méthode ReadUnsignedInt veut revenir.

  

CORRUPTION HEAP DECOUVERTE. CRT a détecté que l'application écrit dans la mémoire après la fin du tampon.

Comme je l'ai lu, cela peut être la cause en essayant de doubler supprimer quelque chose. Cela peut être causé par une utilisation incorrecte de l'std::tr1::shared_ptr mais je ne peux pas déterminer ce que je fais de mal avec eux. Code est la suivante (manipulation omise erreur):

unsigned int Memory::ReadUnsignedInt (unsigned int address) const {
    std::tr1::shared_ptr<byte> bytes = 
        this->ReadBytes(address, sizeof(unsigned int));
    return *((int*)bytes.get());
    // correct value (how to improve this ugly piece of code?)
}

std::tr1::shared_ptr<byte> Memory::ReadBytes (
    unsigned int address, int numberOfBytes) const
{
    std::tr1::shared_ptr<byte> pBuffer(new byte(numberOfBytes));
    ReadProcessMemory(m_hProcess.get(), (LPCVOID)address, 
        pBuffer.get(), numberOfBytes * sizeof(byte), NULL))
    return pBuffer;
}
Était-ce utile?

La solution

Michael et Naveen ont tous deux trouvé le même défaut majeur dans votre code, mais pas le seul défaut.

shared_ptr sera delete le pointé à l'objet lorsque son compteur de références à zéro.

Cela signifie que vous ne pouvez lui donner des objets attribués par new -. Pas new[]

Vous pouvez utiliser shared_ptr<vector<byte> > ou boost::shared_array<byte> à la place.

Autres conseils

La question est:

new byte(numberOfBytes)

alloue un seul octet ayant une valeur de numberOfbytes.

Vous voulez faire:

new byte[numberOfBytes]    

Ce qui alloue un tableau d'octets numberOfbytes longtemps.

Mais puisque vous savez que vous lisez seulement 4 octets, pourquoi la peine allouer de la mémoire à tous? Il suffit de passer l'adresse d'un unsigned int sur la pile.

Les problèmes de base avec votre code ont déjà été signalé. En regardant, je suis à me demander pourquoi vous utilisez un shared_ptr ici du tout, cependant. Si je le faisais, je serais probablement utiliser quelque chose comme ceci:

unsigned Memory::ReadUnsignedInt(unsigned address) { 
    unsigned ret;
    ReadProcessMemory(m_hProcess.get(), (void *)address, &ret, sizeof(ret), NULL);
    return ret;
}

std::vector<char> Memory::ReadBytes(unsigned address, int num) { 
    std::vector<char> ret(num);
    ReadProcessMemory(m_hProcess.get(), (void *)address, &ret[0], num, NULL);
    return ret;
}

Et puis, au lieu de readUnsignedInt, je serais tenté d'utiliser un modèle:

template <class T>
T Memory::Read(unsigned address) { 
    T ret;
    ReadProcessMemory(m_hProcess.get(), (void*)address, &ret, sizeof(ret), NULL);
    return ret;
}

Puisque vous ne passez pas un paramètre à partir duquel il peut déduire le type pour le paramètre de modèle, vous auriez toujours spécifier explicitement:

int x = Read<int>(wherever);
char a = Read<char>(wherever);

L'alternative serait de passer la destination en tant que paramètre:

template <class T>
Memory::Read(unsigned address, T &t) { 
    ReadProcessMemory(my_hProcess.get(), (void *)address, &t, sizeof(t), NULL);
};

que vous souhaitez utiliser comme:

Read(wherever, some_int);
Read(somewhere, some_long);

et ainsi de suite.

Si vous êtes inquiet au sujet de l'inefficacité de retourner un vecteur de char, vous ne devriez probablement pas - VC ++ (comme la plupart des autres compilateurs raisonnablement courants) a ce qu'on appelle une « optimisation du nom de valeur de retour », ce qui signifie que dans une situation comme celui-ci, il passe une référence cachée au vecteur que vous attribuez le résultat et readBytes utilisera que pour déposer les données directement là où il va finir par toute façon. Pour cette question, avec une optimisation raisonnable sous tension du tout, readBytes va presque certainement finir comme une fonction en ligne, donc rien impliqué devient vraiment « passé » ou « retour » du tout.

D'autre part, ce code ne fonctionne pas particulièrement bien avec les compilateurs plus anciens - et avec les anciens compilateurs assez, les versions en utilisant les fonctions de modèle de membre sera probablement même pas compiler. Tant que vous utilisez un compilateur raisonnablement en cours, cependant, la vie devrait être bon.

Je crois new byte(numberOfBytes) devrait être new byte[numberOfBytes]. Sinon, vous auriez alloué un seul octet. Juste pour compléter la réponse, comme indiqué @ephemient vous ne pouvez pas utiliser shared_ptr ici comme il le fera un delete où que vous devriez faire delete[]. Sinon fait comme celui-ci, le comportement sera indéfini.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top