Vraag C # geheugenadres en variabele


in C #, is er een manier om

  1. Download het geheugenadres dat is opgeslagen in a referentietype variabele?
  2. Download het geheugenadres van a variabele?

BEWERK:

int i;
int* pi = &i;
  • Hoe print je de hexadecimale waarde van pi uit?

21
2018-02-26 02:01


oorsprong


antwoorden:


Voor # 2, de & operator zal op dezelfde manier werken als in C. Als de variabele niet op de stapel staat, moet u mogelijk een fixed om het vast te pinnen terwijl je werkt, dus de vuilnisman verplaatst het niet.

Voor # 1 zijn referentietypen lastiger: u moet een GCHandleen het referentietype moet blisbaar zijn, d.w.z. een gedefinieerde geheugenlay-out hebben en bitgewijs kopieerbaar zijn.

Om toegang te krijgen tot het adres als een nummer, kunt u van het aanwijzertype naar casten IntPtr (een geheel getal dat is gedefinieerd als dezelfde grootte als een aanwijzer) en van daar naar uint of ulong (afhankelijk van de pointergrootte van de onderliggende machine).

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
class Blittable
{
    int x;
}

class Program
{
    public static unsafe void Main()
    {
        int i;
        object o = new Blittable();
        int* ptr = &i;
        IntPtr addr = (IntPtr)ptr;

        Console.WriteLine(addr.ToString("x"));

        GCHandle h = GCHandle.Alloc(o, GCHandleType.Pinned);
        addr = h.AddrOfPinnedObject();
        Console.WriteLine(addr.ToString("x"));

        h.Free();
    }
}

13
2018-02-26 02:10



Nummer 1 is helemaal niet mogelijk, u kunt geen aanwijzer naar een beheerd object hebben. U kunt echter een IntPtr-structuur gebruiken om informatie over het adres van de aanwijzer in de verwijzing te krijgen:

GCHandle handle = GCHandle.Alloc(str, GCHandleType.Pinned);
IntPtr pointer = GCHandle.ToIntPtr(handle);
string pointerDisplay = pointer.ToString();
handle.Free();

Voor nummer 2 gebruikt u de operator &:

int* p = &myIntVariable;

Wijzers moeten natuurlijk worden gedaan in een onveilig blok en u moet onveilige code toestaan ​​in de projectinstellingen. Als de variabele een lokale variabele in een methode is, wordt deze toegewezen aan de stapel, zodat deze al is opgelost, maar als de variabele lid is van een object, moet u dat object in het geheugen vastzetten met behulp van de fixed zoekwoord, zodat het niet wordt verplaatst door de vuilnisman.


5
2018-02-26 02:45



Om je vraag het meest correct te beantwoorden:

# 1 is mogelijk, maar een beetje lastig, en zou alleen gedaan moeten worden om reden van debuggen:

object o = new object();
TypedReference tr = __makeref(o);
IntPtr ptr = **(IntPtr**)(&tr);

Dit werkt voor elk object en retourneert in feite de interne aanwijzer naar het object in het geheugen. Onthoud dat het adres op elk moment kan veranderen vanwege de GC, die objecten graag door het geheugen verplaatst.

# 2 Pointers zijn geen objecten en nemen dus niet over ToString van hen. Je moet de wijzer naar toe werpen IntPtr zoals zo:

Console.WriteLine((IntPtr)pi);

2
2017-12-10 16:14