14.12.2011 21:31

Jak zjistit ukazatel na objekt

Narozdíl od C++ se C# postaral o to, aby nám zjištění ukazatele co nejvíc ztížil. Přesto je to možné. Pokusíme se zjistit ukazatel do paměti na objekt o:

object o = new Object();

Jako první možnost by připadalo použití unsafe kontextu a &o. Unární operátor & ale funguje jen na instance struktur (by-val). Pokud by typ o byl struktura, je toto použití nejlepší.

Co ale v případě, že typ o je instance třídy nebo jiných typů než struktury (by-ref)? Pak existuje několik způsobů. První je použití struktury GCHandle, která získá odkaz na objekt v rámci garbage collectoru.

GCHandle handle = GCHandle.Alloc(o);
GCHandle.ToIntPtr(handle);

Metoda ToIntPtr získá ukazatel, ale při každém dalším alokování se bude měnit. Částečně to řeší konstruktor GCHandle.Alloc(o, GCHandleType.Pinned), tento způsob ale lze použít jen na některé objekty.

Druhý způsob je vytvoření pole a zjištění ukazatele na první index.

object[] arr = new object[1]{o};
Marshal.UnsafeAddrOfPinnedArrayElement(arr, 0);

Toto lze použít pro všechny objekty, ale nevýhoda spočívá ve vytvoření samotného pole. Stává se totiž, že se ukazatel změní z důvodu přesunutí objektu v paměti v rámci fragmentace.

Poslední a funkční způsob je vytvoření tzv. typové refence (TypedReference), která slouží k získání managed reference na objekt a jeho typ. Je potřeba v metodě použít atribut unsafe a kód kompilovat s přepínačem "/unsafe".

//Ve třídě:
[StructLayout(LayoutKind.Sequential)]
struct TypedReferenceStructure
{
    public IntPtr Value;
    public IntPtr Type;
}


//V metodě:
TypedReference r = __makeref(o);
TypedReferenceStructure rs = *((TypedReferenceStructure*)&r);

Struktura TypedReferenceStructure složením odpovídá struktuře TypedReference. Díky tomu lze mezi nimi přes ukazatele převádět. Pole rs.Value obsahuje ukazatel na objekt o. Pole rs.Value obsahuje ukazatel na proměnnou o – nikoliv na samotný objekt –, která obsahuje ukazatel na objekt o – *((IntPtr*)rs.Value) vrací ukazatel typu IntPtr na objekt. V paměti je třída reprezentována odlišně než struktura, neboť má 4-bajtovou hlavičku. 5. bajt je začátek samotných dat. Kód ((byte*)*((IntPtr*)rs.Value))[4] zjistí první bajt dat polí třídy.

Napsal jsem, že je lze převádět i obráceně. Tento způsob ale nedoporučuji, protože je velká šance výskytu různých chyb. Předpokládejme, že máme strukturu A s jediným veřejným polem f typu int.

TypedReferenceStructure rs = new TypedReferenceStructure();
A a = new A();
a.f = 256;
rs.Value = (IntPtr)(&a);
rs.Type = typeof(A).TypeHandle.Value;
TypedReference r2 = *((TypedReference*)&rs);
A x = __refvalue(r2, A);


Console.WriteLine(x.f);

Z tohoto kódu je patrné, že lze typovou referenci tímto způsobem i vytvořit a ručně jí přiřadit hodnoty. Pole Type musí být nastaveno na správný typ (se správným složením), jinak vzniknou problémy, např. že typ x nebude dědit System.Object. Pokud by vše proběhlo správně, mělo by se vypsat 256.

Získání ukazatele na objekt a manipulace s ním je složitá a náchylná na chyby a proto se nedoporučuje.

Editace 5.2.2012: Stejnou metodou, jakou jsem přetypoval TypedReference na TypedReferenceStructure, jde díky typové referenci přetypovat jakýkoliv objekt na jiný typ.

// Je třeba zkompilovat s přepínačem /unsafe
/// <summary>Nastaví typ reference na 'object' na T2 a novou referenci vrátí.</summary>

/// <param name="object">Objekt, jehož referenci se nastaví nový typ.</param>
/// <returns>Reference na 'object' s novým typem.</returns>
public static unsafe T2 ChangeReferenceType<T1, T2>(T1 @object)
{
    TypedReference typedref = __makeref(@object);
    IntPtr* ptr = (IntPtr*)&typedref;
    ptr[1] = typeof(T2).TypeHandle.Value;
    return __refvalue(typedref, T2);
}

Typové parametry metody ChangeReferenceType musí být oba právě by-ref, nebo by-val.

—————

Zpět


Diskusní téma: Jak zjistit ukazatel na objekt

Datum: 07.06.2018

Vložil: AlbertOxift

Titulek: How To Prevent Prostate Problems And Diseases?

The prostate related is central to the section of a male's the reproductive system. It secretes fluids that assist the transportation and activation of sperm. The prostate can be found just as you're watching rectum, below the bladder and around the urethra. When there is prostate problem, it is usually very uncomfortable and inconvenient for your patient as his urinary strategy is directly affected.

The common prostate health conditions are prostate infection, enlarged prostate and cancer of the prostate.



Prostate infection, also known as prostatitis, is regarded as the common prostate-related overuse injury in men younger than 55 years of age. Infections in the prostate related are classified into four types - acute bacterial prostatitis, chronic bacterial prostatitis, chronic abacterial prostatitis and prosttodynia.

Acute bacterial prostatitis may be the least common of all varieties of prostate infection. It is caused by bacteria based in the large intestines or urinary tract. Patients may feel fever, chills, body aches, back pains and urination problems. This condition is treated through the use of antibiotics or non-steroid anti-inflammatory drugs (NSAIDs) to help remedy the swelling.

Chronic bacterial prostatitis is really a condition of a particular defect in the gland and the persistence presence of bacteria within the urinary tract. It can be brought on by trauma on the urinary tract or by infections received from the rest in the body. A patient can experience testicular pain, small of the back pains and urination problems. Although it is uncommon, it may be treated by removal with the prostate defect as well as the employment antibiotics and NSAIDs to deal with the redness.

Non-bacterial prostatitis is the reason for approximately 90% of all prostatitis cases; however, researchers have not even to establish the cause of these conditions. Some researchers think that chronic non-bacterial prostatitis occur as a consequence of unknown infectious agents while other believe intensive exercise and lifting may cause these infections.

Maintaining a Healthy Prostate

To prevent prostate diseases, a proper diet is important. These are some of the actions to keep your prostate healthy.

1. Drink sufficient water. Proper hydration is necessary for health and wellness and it will also maintain your urinary track clean.

2. Some studies suggest that a couple of ejaculations a week will help to prevent prostate cancer.

3. Eat steak moderately. It has been shown that consuming over four meals of beef a week will increase the risk of prostate diseases and cancer.

4. Maintain an effective diet with cereals, vegetable and fruits to ensure sufficient intake of nutrients required for prostate health.

The most crucial measure to take to be sure a proper prostate is to opt for regular prostate health screening. If you are forty years of age and above, you should select prostate examination at least once annually.

Odpovědět

—————