2009-05-28 10 views
4

Fondamentalement, je voudrais stocker l'adresse d'un pointeur dans un tampon. Ne me demandez pas pourquoiCopie d'un entier dans un memcpy Buffer C++

char * buff = "myBuff"; 
char * myData = (char*)malloc(sizeof(char*)); 
int addressOfArgTwo = (unsigned int)buff; 
memcpy(myData, &addressOfArgTwo, sizeof(char*)); 

cout << "Int Val: " << addressOfArgTwo << endl; 
cout << "Address in buffer:" << (unsigned int)*myData << endl; 

Je ne vois pas pourquoi le code ci-dessus ne fonctionne pas. Il produit:

Int Val: 4472832 
Address in buffer:0 

Lorsque Int Val & Adresse dans le tampon doit être le même. merci

+0

Merci pour votre aide tout –

Répondre

8

Vous déréférencer un char *, résultant en un char, puis de transformer ce char 1 octet à un int, pas les 4 octets entiers de l'adresse (s'il s'agit d'une machine 32 bits, 8 octets sur 64- bit). 4472832 est 444000 en hexadécimal. Sur une machine little-endian, vous saisissez ce dernier 00.

*((unsigned int*)myData) 

devrait donner le nombre correct affiché.

1
Instead of (int)*myData, it should be *((int*)myData) 
1

comme Michael a dit cette ligne devrait être

cout << "Address in buffer:" << *((unsigned int*)myData) << endl 
1

Ceci est généralement dangereux:

*((unsigned int*)myData) 

Intel IA-32 (que tout le monde est utilisé pour) prend en charge les accès non alignés, mais un autre les architectures ne le font pas. Ils nécessitent l'alignement des variables (données de 8 bits sur les limites de 1 octet, données de 16 bits sur les limites de 2 octets et données de 32 bits sur les limites de 4 octets). Sur une architecture qui nécessite un alignement, un accès non aligné renverra des données corrompues ou déclenchera une exception de CPU. Je l'ai vu causer un bogue dans la vie réelle à un travail passé, un bug subtil qui a causé la corruption du système de fichiers en raison du pilote de disque fourni avec un logiciel que nous utilisions (sur une plate-forme intégrée). Dans ce cas isolé, vous pouvez voir que l'adresse de myData provient de malloc(), ce qui signifie qu'elle est correctement alignée pour tous les types de pointeurs, mais le fait de lancer un pointeur plus petit vers un pointeur plus grand est généralement une pratique dangereuse. Je ne sais pas d'où vient le pointeur.

Le moyen sûr pour extraire un emplacement de mémoire arbitraire nombre entier de 32 bits à partir d'un consiste à déclarer un entier de 32 bits temporaire et effectuer une copie à elle, le traitement de la mémoire source en tant que matrice de caractère brut:

unsigned int GetUnalignedLittleEndianUInt32(void *address) 
{ 
    unsigned char *uc_address = (unsigned char *)address; 
    return (
     (uc_address[3] << 24) | 
     (uc_address[2] << 16) | 
     (uc_address[1] << 8) | 
     uc_address[0] 
    ); 
} 

ou plus généralement (avec une surcharge d'appel de fonction):

unsigned int GetUnalignedUInt32(void *address) 
{ 
    unsigned int value; 
    memcpy(&value, address, sizeof(value)); 
    return value; 
} 

qui est en fait juste l'inverse de la memcpy() vous avez fait pour obtenir le pointeur là en premier lieu.

Bien que, le traitement du pointeur comme un entier:

int addressOfArgTwo = (unsigned int)buff; 

est également dangereux, si vous vous déplacez entre 32 bits et les architectures 64 bits, comme Michael a fait remarquer. Les pointeurs ne sont pas toujours des entiers 32 bits. Pensez à utiliser un typedef que vous pourrez modifier ultérieurement. La convention sur Linux est pour un pointeur d'avoir la même taille qu'un long. Sous Windows, il y a typedefs INT_PTR, UINT_PTR, LONG_PTR et ULONG_PTR.

Alors, je suggère enfin (sous Windows de toute façon):

ULONG_PTR GetAddressAtAddress(void *address) 
{ 
    ULONG_PTR value; 
    memcpy(&value, address, sizeof(value)); 
    return value; 
} 
Questions connexes