2016-07-19 18 views
2

In C#, wenn ich eine Hash-Tabelle erstellen und die Speicheradresse abrufen, in der es gespeichert ist, kann ich diese Speicheradresse in einem anderen Teil des Programms verwenden, um die Hash-Tabelle neu zu erstellen?Gibt es eine Speicheradresse, ist es möglich, ein Objekt daraus zu erstellen?

Zum Beispiel kann ich tun, so etwas wie:

HashTable hash = new HashTable(oldHashPointer); 
+0

In welcher Sprache? Was meinst du mit "neu erstellen"? – nhouser9

+0

In C#, und ich meine etwas wie "HashTable ht = neue HashTable (intptr)", die eine Kopie der Hash-Tabelle erstellen soll, die an dieser Adresse ist. –

+0

Eine gültige Objektadresse in C# befindet sich immer im GC-Heap. Diese Adresse kann nur dann gültig bleiben, wenn das Objekt * angeheftet * ist, so dass der GC das Objekt nicht erfassen oder verschieben kann. GCHandle ist erforderlich, ein Zeiger ist nie gut genug. Sie können die Objektreferenz immer mit der GCHandle.Target-Eigenschaft wiederherstellen. Das 'unsichere' Schlüsselwort bedeutet, was es sagt, mit Zeigern geht nicht oft genug schief. –

Antwort

3

Ja und nein. Dies ist in C# nicht so möglich, wie Sie es beschreiben. Zum Beispiel der folgende Code:

HashTable a = new HashTable(); 
HashTable b = a; 

ist im Wesentlichen, was Sie zu tun versuchen, ohne explizite Zeiger Nutzung. HashTable b ist keine separate Einheit, es ist ein Zeiger auf den in HashTable a gespeicherten Verweis, der auf ein HashTable Objekt im Speicher zeigt.

This MSDN article erarbeitet auf diese. Ein Zitat von der Seite:

Zeiger Typen erben nicht von Objekt und keine Konvertierungen existieren zwischen Zeigertypen und Objekt. Boxing und Unboxing unterstützen auch nicht Zeiger .

jedoch, wenn Sie versuchen, Objekte zwischen Prozessen zu teilen (in diesem Fall ein HashTable), könnten Sie in Memory Mapped Files aussehen. Diese ermöglichen es Ihnen im Wesentlichen, ein serialisiertes Objekt in eine virtuelle "Datei" zu schreiben, die sich im Speicher befindet, auf die auch von dem anderen Prozess zugegriffen werden kann. Dies ist jedoch nur in .NET 4.0 oder neuer verfügbar.

+0

Gibt es also eine Möglichkeit, einen Verweis auf die Speicheradresse zu erstellen? z.B. HashTable b = neue HashTable (Adresse); –

+0

Nein, Sie können einen Referenzzeiger nicht in ein Objekt konvertieren. Diese MSDN-Seite arbeitet daran; https://msdn.microsoft.com/en-us/library/y31yhkeb.aspx. Woher bekommst du diese "Adresse"? –

+0

Ich habe eine Hash-Tabelle in Prozess A, und ich versuche, es aus Prozess B zu lesen. Ich kann die Speicheradresse der Hash-Tabelle Prozess B übergeben. Ich weiß, es gibt andere Methoden, aber ich versuche speziell zu bekommen Diese Methode funktioniert. –

-1

C# ist referenzbasiert, dh Sie können mehrere Variablen erstellen, die auf dieselbe Instanz verweisen.

ext10 gab bereits ein schönes Beispiel dafür. Also etwas in hasttable a hinzufügen, dann ist es auch für b verfügbar. Weil sie dieselbe Instanz sind.

0

Es ist möglich. Wie es tun:

  1. Ihre Klasse markiert werden müssen, mit [StructLayout (LayoutKind.Sequential)] oder (LayoutKind.Explicit)
  2. Sie in nicht verwalteten Speicher benötigte Menge an Bytes var ptr zuweisen sollte = Marshal.AllocHGlobal (Marshal.SizeOf (Typ von (T)));
  3. Kopieren Sie Ihr Objekt auf diesen Zeiger Marshal.StructureToPtr (obj, ptr, false);
  4. Erstellen Sie newObj und kopieren Sie Daten zu diesem Objekt Marshal.PtrToStructure (ptr, newObj);
  5. Vergessen Sie nicht, nicht verwalteten Speicher zu befreien, oder Sie erhalten Speicherlecks Marshal.FreeHGlobal (ptr);

Update:

Code:

namespace MarhsalExampe 
{ 
    using System; 
    using System.Runtime.InteropServices; 
    public class Program 
    { 
     [StructLayout(LayoutKind.Sequential)] 
     public class SomeClass 
     { 
      public int IntProp { get; private set; } 
      public string StrProp { get; private set; } 
      public double DoubleProp { get; private set; } 
      public bool BoolProp { get; private set; } 

      public SomeClass() { } 
      public SomeClass(int i, string s, double d, bool b) 
      { 
       IntProp = i; 
       StrProp = s; 
       DoubleProp = d; 
       BoolProp = b; 
      } 
      public override string ToString() 
      { 
       return string.Format("HashCode: {0}, IntProp: {1}, StrProp: {2}, DoubleProp: {3}, BoolProp: {4}", 
        GetHashCode(), IntProp, StrProp, DoubleProp, BoolProp); 
      } 
     } 
     public static void Main() 
     { 
      var obj = new SomeClass(42, "42", 42.0, true); 
      Console.WriteLine("Obj is: {0}", obj); 

      IntPtr ptr = IntPtr.Zero; 
      try 
      { 
       // Allocate memory in unmanaged memory 
       ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SomeClass))); 
       // Copy data to ptr 
       Marshal.StructureToPtr(obj, ptr, false); 
       Console.WriteLine("Pointer: 0x{0:X}", ptr.ToInt64()); 

       // Create new object 
       var newObj = new SomeClass(); 
       Console.WriteLine("newObj before updating from pointer: {0}", newObj); 
       // Copy data to new object 
       Marshal.PtrToStructure(ptr, newObj); 

       Console.WriteLine("newObj after updating: {0}", newObj); 
      } 
      finally 
      { 
       if (ptr != IntPtr.Zero) 
        Marshal.FreeHGlobal(ptr); 
      } 
     } 

    } 
} 
+0

OP versucht, von einem anderen Prozess auf eine HashTable zuzugreifen. Ich denke, es wird eine Verletzung des Prozessadressbereichs auslösen, wenn der andere Prozess versucht, vom 'ptr' zu lesen. –

+0

@ ext0, zum Lesen eines anderen Prozesses privaten Speichers kann man [ReadProcessMemory] (https://msdn.microsoft.com/en-us/library/ms680553 (v = vs.85) .aspx) verwenden. Der Prozess muss das Prozessrecht [PROCESS_VM_READ] (https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms684880 (v = vs.85) .aspx) haben und auch unter Admin-Rechten und SeDebugPrivilege gestartet sein. –