c ++ - tildele NULL til x64 pointers

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har en proces, der kører fint på x86 platforme.

Nu har jeg samlet det til x64 og pludselig kan jeg ikke tildele NULL til mine pointers.

Hvis jeg gør noget som dette:


void* pointy = NULL;


Det vil pege på 0x0000000100000000

Hvad sker der?

Bedste reference


Null er ikke nødvendigvis bitvis nul. Dens værdi er implementeringsdefineret.





Det vil sige, disse er alle de samme:


void* pointy = NULL;
void* pointy = 0;
void* pointy = nullptr;


De tildeler en nullpegerværdi til pointy. Hvad denne værdi er på et bitniveau er helt uspecificeret, og er ikke nødvendigvis alle bits nul!


Hvis din kode er, hvad du siger, er det enten: din platform bruger faktisk den værdi til null, det gør det ikke, og din compiler er brudt, eller det læser du ikke værdien forkert.


Under alle omstændigheder er C ++-koden fint, og sætter pointy til null. Du behøver ikke bekymre dig om noget mere.

Andre referencer 1


Når du udfører et program, der indeholder:


void* pointy = NULL;


den initialiserer pegerobjektet pointy, så det indeholder en nullpeger -værdi (forudsat at du [[ve]] #include d et af de overskrifter, der definerer NULL makroen) .


En nullpeger er en værdi af en given pegertype, der adskiller sig fra enhver anden værdi af den pågældende type. Logisk er det en pointer, der ikke peger på noget.


En null-pointer kan repræsenteres i C ++-kildekoden med en null-pegekonstant . NULL er en makro, der udvider til en nullpegekonstant. En bogstavlig 0 er også en nullpegekonstant, ligesom søgeordet nullptr (en ny tilføjelse til sproget). Dette betyder ikke nødvendigvis, at en nullpegerværdi er repræsenteret som all-bits-nul, men det er normalt, og jeg er villig til at vædde på, at den er på dit system.


Hvis du udskriver værdien af ​​pointy:


std::cout << "pointy = " << pointy << "
";


du vil se en implementeringsdefineret repræsentation af en nullpeger. På mit system udskriver den pointy = 0. På andre systemer kan det være 0x0 eller [null] eller næsten alt andet , men det skal være genkendeligt som en nullpeger.


For at teste om værdien af ​​pointy er en nullpeger, sammenlign den i dit program:


if (pointy == NULL) {
    std::cout << "Yes, it's a null pointer
");
}
else {
    std::cout << "No, it's not a null pointer (?)
");
}


Bemærk at du ikke kan genkende pointy for at bestemme, hvad det peger på, fordi det er af typen void*. Hvis det var af en anden pegertype, som f.eks. int*, kunne du skrive kode for dereference det, men opførelsen af ​​den kode ville være udefineret; den mest sandsynlige adfærd ville være et programkrasch, men alting er muligt.


Hvad du ser i din debugger, kan jeg ikke gætte uden yderligere oplysninger. Det er muligt, at din debugger virker forkert, men det er usandsynligt. Det er muligt, at du ser på, hvad pointy peger på (sandsynligvis ved hukommelsesadresse 0), men det er heller ikke sandsynligt, da en void* peger ikke peger på data af nogen specificeret type, der er ingen måde for debugger at vise det.


Kan det være, at du har sat et breakpoint i definitionen af ​​pointy, og kigger på den værdi, der er gemt i den, når du rammer breakpoint? Hvis det er tilfældet, kan du måske bare se værdien før initialiseringen sker. Prøv at gå fremad en linje og se på værdien igen. Hvis dette syntes at fungere korrekt på x86, skyldes det sandsynligvis, at det affald, som pointy indeholdt inden det blev initialiseret, skete at ligne en nullpeger.


Under alle omstændigheder siger C ++-sproget intet om, hvad du vil se, når du bruger en debugger, det definerer kun et programs opførsel som det er. Hvis du har problemer med at bruge din debugger, så er det et legitimt spørgsmål, men du skal fortælle os, hvad debugger du bruger, præcis hvad du gør med det og vise os et lille komplet program, der viser problem.


EDIT: I en kommentar til et andet svar skrev du



  Jeg vil 'pointy' til at pege på 0.



Der er mindst to meget forskellige ting, der kan betyde.


Dette:


int* ptr = new int(0);


forårsager ptr at pege på en genstand et sted i hukommelsen; den pågældende genstand indeholder værdien int 0. Du kan sige, at 'ptr peger på 0', men det ville være mere præcist at sige, at 'ptr peger på et objekt, hvis værdi er 0'.


Dette:


int *nptr = 0;


forårsager nptr s værdi til at være en nullpeger . Det er nok det, du mener med 'point til 0', men det er bedre at sige at nptr s værdien er en nullpeger. (Hvis du ser nptr som en maskinniveauadresse, er det sandsynligt, at det indeholder adressen til hukommelsesstedets nul, med andre ord peger nptr til hukommelsesstedet 0 . Men i C ++-termer peger det ikke rigtigt på nogen hukommelsesplacering ved alll; en nullpegerværdi er en speciel adresselignende værdi, der bruges til at skelne pointers, der ikke henviser til steder fra peger, der peger på objekter.)


Hvad du virkelig vil, tror jeg, er for pointy at indeholde en nullpegerværdi og koden du viste os:


void* pointy = NULL;  // or 0, or nullptr


er netop den rigtige måde at gøre det på.