2017-04-03 521 views
0

嗨我正在使用Protobuf進行關於神經網絡的個人項目。釋放Protobuf生成的類會導致段錯誤

這裏是我的Protobuf定義:

syntax = "proto3"; 

package NGNET; 

message InputLayer { 
    string name = 1; 
    uint32 size = 2; 
} 

message ComputeLayer { 
    string name = 1; 
    uint32 size = 2; 
    repeated LayerLink inputs = 3; 
} 

message LayerLink { 
    InputLayer il_input = 1; 
    ComputeLayer cl_input = 2; 
    uint32 output_size = 3; 
    repeated float weights = 4; 
} 

message NNET { 
    string name = 1; 
    repeated ComputeLayer outputs = 3; 
} 

網絡創建這樣的:

ComputeLayer output1 = ComputeLayer(10, "output1"); 
ComputeLayer output2 = ComputeLayer(10, "output2"); 
ComputeLayer hidden = ComputeLayer(100, "hidden"); 
InputLayer input1 = InputLayer(784, "input1"); 
InputLayer input2 = InputLayer(784, "input2"); 

output1.link(&hidden); 
output2.link(&hidden); 
hidden.link(&input1); 
hidden.link(&input2); 
hidden.link(&extra); 

鏈接功能被定義爲:

void ComputeLayer::link(ComputeLayer* to_link) { 
    NGNET::LayerLink* link = new NGNET::LayerLink(); 
    link->set_output_size(internal->size()); 
    link->set_allocated_cl_input(to_link->getInternal()); 
    internal->mutable_inputs()->AddAllocated(link); 
} 

void ComputeLayer::link(InputLayer* to_link) { 
    NGNET::LayerLink* link = new NGNET::LayerLink(); 
    link->set_output_size(internal->size()); 
    link->set_allocated_il_input(to_link->getInternal()); 
    internal->mutable_inputs()->AddAllocated(link); 
} 

注:getInternal()功能返回NGNET::ComputeLayerNGNET::InputLayer

然後輸出被喜歡一個NNET與:

nnet->mutable_outputs()->AddAllocated(output1->getInternal()); 
nnet->mutable_outputs()->AddAllocated(output2->getInternal()); 

nnet時用段故障刪除的程序崩潰。

我相信這是由於隱藏層被刪除兩次。有什麼方法可以安全地釋放分配的內存嗎?

謝謝。

+0

你必須弄清楚誰在你的設計中擁有什麼。目前,你告訴多方他們都擁有相同的信息,當然他們都試圖刪除它,導致雙重破壞。例如。 'set_allocated_Foo'應該是通過'release_Foo'從一個指向前一個擁有者的指針上調用的 - 但是你傳遞給它一個仍然由另一個proto擁有的指針。 –

+0

@IgorTandetnik當你說「你必須弄清楚誰在設計中擁有什麼」時,你的意思是我的設計不適合在Protobuf中使用,或者我應該利用Protobuf的其他一些我不知道的功能的? –

+0

我不太瞭解你的設計。從表面上看,你似乎試圖對共享所有權建模。 Protobufs的設計是爲了讓每條消息嚴格擁有其字段的值(本身可以是消息),並認爲自己負責銷燬它們。你不能讓'LayerLink'原型只指向一個'ComputeLayer'原型,而不會在前者本身被破壞時試圖破壞後者。任何共享所有權都必須由您自己的類在protobuf庫之外進行建模。 –

回答

0

add_allocated_*()set_allocated_*()方法取得所有權指針它們被給予。這意味着你必須確保沒有其他代碼會在以後刪除這些指針,因爲當消息被銷燬時,Protobuf實現將刪除它們。

如果你不想的Protobuf採取這些對象的所有權,你應該做的副本,而不是:

link->mutable_il_input()->CopyFrom(*to_link->getInternal()); 

nnet->mutable_outputs()->Add()->CopyFrom(*output2->getInternal()); 

一般來說,除非你正在做激烈的內存分配優化,你可能永遠要撥打的「分配「protobuf訪問器。