Go-Ethereum

映射上的“刪除”真的可以釋放記憶體空間嗎?

  • November 11, 2016

我有以下mapping(uint => Foo[])資料結構。我用 10 個 Foo 結構映射了 10 個唯一 ID,其中每個 Foo 是一個包含 10 個項目的數組列表。

第1步:

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

**第2步:**我刪除之前推送的項目。我不確定下面的 a) 和 b) 中哪一個是正確的方法。方法 b) 通過僅重置結構中的成員來留下漏洞

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)  

**第 3 步:**我推送具有不同映射 uint id 的新項目。

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

$$ Q $$實際上會delete mapping_array[id]釋放由數組列表分配的記憶體mapping嗎?或者它是否只會將記憶體歸零,就像delete在 Array List 上使用一樣,並且該項目仍然mapping是空的,但仍然佔用記憶體空間? $$ Q $$總的來說,我用 10 個 Foo 結構映射了 10 個唯一 ID,其中每個 Foo 是一個包含 10 個項目的數組列表。後來我刪除了mapping資料結構中的項目,然後將新項目插入其中。那麼新插入的項目會獲得為它們分配的新記憶體,還是會在最近刪除的項目的記憶體中被覆蓋? 這些很重要,因為我使用的是非常大的映射資料結構,並且經常插入和刪除項目。我知道 delete 不會釋放數組上的記憶體,但不確定它在映射中是否相同。

我正在使用這個問題的答案中的以下程式碼片段: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];
 }

刪除:

delete a 將類型的初始值分配給 a。即對於整數,它相當於a = 0,對於結構,它分配一個所有成員重置的結構。

delete 對整個映射沒有影響(因為映射的鍵可能是任意的並且通常是未知的)。因此,如果您刪除一個結構,它將重置所有不是映射的成員,並且還會遞歸到成員中,除非它們是映射。但是,可以刪除單個鍵及其映射的內容。

重要的是,刪除 a 的行為就像對 a 的賦值,即它在 a 中儲存了一個新對象。

連結:http ://solidity.readthedocs.io/en/develop/types.html

感謝您寶貴的時間和幫助。

根據我的調試觀察:

我已經測試過:

  • 首先,正如我在問題中解釋的那樣,我將數據插入到我的地圖資料結構中。
  • 其次,我返回了第一個映射索引的地址,即 0,這也可以用於其他索引(0:10)。
  • 如果沒有刪除操作,我可以從映射的 Foo 的地址中很好地檢索數據$$ $$. 但是如果我做了刪除操作,Solidity 會報錯。

此調試結果:使我得出結論,記憶體已釋放或地址不包含任何有效資訊。

測試程式碼:

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

我的契約中的附加功能:

 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;  
 }

引用自:https://ethereum.stackexchange.com/questions/9601