映射上的“刪除”真的可以釋放記憶體空間嗎?
我有以下
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; }