Gibt "Löschen" beim Mapping wirklich Speicherplatz frei?

Ich habe folgende mapping(uint => Foo[])Datenstruktur. Ich habe 10 eindeutige IDs mit 10 Foo-Strukturen zugeordnet, wobei jedes Foo eine Arraylist mit 10 Elementen ist.

Schritt 1:

for(int i = 0; i < 10; i++)
   for(int j = 0; j < 10; j++)
       add(i, j); 

Schritt 2: Ich lösche die zuvor gepushten Elemente. Ich bin mir nicht sicher, welcher der richtige Ansatz unter a) und b) unten ist. Ansatz b) hinterlässt Lücken, indem nur die Mitglieder in der Struktur zurückgesetzt werden

a)  for(int i = 0; i < 10; i++)      | b) for(int i = 0; i < 10; i++)
           delete(i);                |      for(int j = 0; j < 10; j++)
                                     |          delete_items(i, j)  

Schritt 3: Ich pushe neue Elemente mit unterschiedlicher Mapping-Uint-ID.

for(int i = 20; i < 30; i++)
   for(int j = 20; j < 30; j++)
       add(i, y); 

[F] Würde delete mapping_array[id]tatsächlich der Speicher freigegeben, der von der Array-Liste innerhalb der mapping? Oder würde es nur den Speicher auf Null setzen, als ob deleteer in der Array-Liste verwendet wurde, und das Element bleibt mappingso leer, nimmt aber immer noch Speicherplatz in Anspruch?

[F] Insgesamt habe ich 10 eindeutige IDs mit 10 Foo-Strukturen zugeordnet, wobei jedes Foo eine Arrayliste mit 10 Elementen ist. Später lösche ich die Elemente in meiner mappingDatenstruktur und füge dann neue Elemente ein. Würde den neu eingefügten Elementen also neuer Speicher zugewiesen oder würden sie im Speicher kürzlich gelöschter Elemente überschrieben?

Diese sind wichtig, da ich eine sehr große Mapping-Datenstruktur verwende und Elemente häufig eingefügt und entfernt werden. Ich weiß, dass Löschen keinen Speicher auf einem Array freigibt, bin mir aber nicht sicher, ob es beim Mapping dasselbe ist.

Ich verwende das folgende Codestück aus der Antwort auf diese Frage: https://ethereum.stackexchange.com/a/1458/4575

  struct Foo{
    uint x;
  }
  mapping(uint => Foo[]) mapping_array;

  function add(uint id, uint _x) public {
    mapping_array[id].push(Foo(_x));
  }

  function get(uint id, uint index) public returns(uint){
    return mapping_array[id][index].x;
  }

  function delete_(uint id) public {
    delete mapping_array[id];
  }

  function delete_items(uint id, uint index) public {
    delete mapping_array[id][index];
  }

Löschen:

a löschen weist a den Anfangswert für den Typ zu. Dh für Integer ist es äquivalent zu a = 0, Für Structs weist es ein Struct zu, bei dem alle Mitglieder zurückgesetzt sind.

delete hat keine Auswirkung auf ganze Mappings (da die Schlüssel von Mappings willkürlich sein können und im Allgemeinen unbekannt sind). Wenn Sie also eine Struktur löschen, werden alle Elemente zurückgesetzt, die keine Zuordnungen sind, und auch in die Elemente rekursiv, es sei denn, es handelt sich um Zuordnungen. Einzelne Tasten und ihre Zuordnung können jedoch gelöscht werden.

Wichtig ist, dass sich das Löschen von a wirklich wie eine Zuweisung zu a verhält, dh es speichert ein neues Objekt in a.

Link: http://solidity.readthedocs.io/en/develop/types.html

Vielen Dank für Ihre wertvolle Zeit und Hilfe.

Versuchen Sie, den Code zu debuggen, und Sie erhalten die Antwort
Das habe ich, aber wie konnte ich verstehen, dass der Speicher freigegeben wird?
Nachdem alle Einfügeoperationen durchgeführt wurden, zum Beispiel: delete mapping_array[0]; entfernt die Zuordnung und wenn ich versuche, mapping_array[0][index].data Solidity aufzurufen, gibt es einen Fehler. Es entfernt also die Zuordnung, sollte ich davon ausgehen (oder auf Solidity vertrauen), dass auch Speicher freigegeben wird?
@BadrBellaj, bitte sehen Sie sich meine Frage noch einmal an, ich habe sie erweitert.

Antworten (1)

Basierend auf meiner Debug-Beobachtung:

Ich habe das getestet:

  • Zuerst füge ich Daten in meine Kartendatenstruktur ein, wie ich in meiner Frage erklärt habe.
  • Zweitens habe ich die Adresse des ersten zugeordneten Index zurückgegeben, die 0 ist, dies könnte auch für andere Indizes erfolgen (0:10).
  • Ohne einen Löschvorgang kann ich die Daten problemlos von der Adresse von gemapptem Foo [] abrufen. Aber wenn ich den Löschvorgang durchgeführt habe, gibt Solidity einen Fehler aus.

Dieses Debug-Ergebnis: führt mich zu dem Schluss, dass Speicher freigegeben wird oder die Adresse keine gültigen Informationen enthält.

Testcode:

set_txn_hash     = my_contract.transact().map_insert();
contract_address = unmigrated_chain.wait.for_receipt(set_txn_hash)

for x in range(0, 9):
   for y in range(0, 9):
         output           = my_contract.call().get_(x, y);
         print(output);  //returns correct value.

set_txn_hash     = my_contract.transact().map_remove_map();                                             
contract_address = unmigrated_chain.wait.for_receipt(set_txn_hash)                                      

set_txn_hash     = my_contract.transact().get_map_address(0);
contract_address = unmigrated_chain.wait.for_receipt(set_txn_hash)

output           = my_contract.call().get_map();
print(output);

output           = my_contract.call().try_();
print(output);  //Solidity gives error if delete map_remove_map() is called

Zusätzliche Funktionen in meinem Vertrag:

  function map_insert(){
    for(uint i = 0; i < 10; i++)
      for(uint j = 0; j < 10; j++)
        add(i, i*10 + j);
  }

  function map_remove_map(){
    for(uint i = 0; i < 10; i++)
      delete_(i);
  }

  function map_remove_map_item(){
    for(uint i = 0; i < 10; i++)
      for(uint j = 0; j < 10; j++)
        delete_items(i, j);
  }

  function get_map_address(uint id) {
    uint addr;
    Foo[] a = foo[id];

    assembly{
    addr := a
        }
    map_address = addr;
  }

  function get_map() constant returns (uint){
    return map_address;
  }

  function try_() constant returns (uint ){
    uint addr = map_address;
    Foo[] a;
    assembly{
    a := addr
        }
    return a[1].x;  
  }
Wenn ich es richtig verstehe, widersprechen diese Ergebnisse dem, was in der Dokumentation geschrieben steht. Irgendeine Idee, wieso?
Gepushter Speicher wird niemals gelöscht, da es für alle Tausend Knoten sehr teuer ist, ihn zu entfernen, der sich in den Löchern im Array befinden könnte. Als einfache Lösung, wie ich es verstehe, machen sie den Speicher einfach gleich Null. Beziehen Sie sich auf Solidity Doc? @DavidAmmouial