2011-06-22 202 views
0
void ServerManager::addWork(SocketClient *clientSocket, vector<char> data){ 
    Work *work = new Work(clientSocket, data); 
    m_workHandler->addWork(work); 
} 

這裏我創建了Work實例並將工作交給WorkHandler。我應該在哪裏釋放物體?

m_workHandler->addWork(work); 

此代碼將工作插入到隊列中。

這是我的服務器的一個組成部分,如果我在很長一段時間這個代碼,然後錯誤的服務器崩潰說這樣

what() std::bad_alloc 

我在網上看了看,它是顯示有ISN的錯誤消息」 t可用內存空間。所以我意識到在完成使用後我沒有釋放工作對象。

所以我想知道在哪裏我應該釋放工作對象。

void ServerManager::addWork(SocketClient *clientSocket, vector<char> data){ 
    Work *work = new Work(clientSocket, data); 
    m_workHandler->addWork(work); 
    delete work; 
} 

我可以這樣做嗎?如果我通過工作實例,那麼它會增加引用計數?

void WorkHandler::workLoop(){ 
    printf("WorkHandler::workLoop, called\n"); 

    while(m_workHandlerRun){ 
     Work *work = getWork(); 
     char *pdata = work->getVPointer(); 

     unsigned char type = pdata[0]; 

     printf("WorkHandler::workLoop, type %d\n", type); 

     Packet *packet = m_packetFactory->createInstance(static_cast<PACKET_TYPES>(type)); 
     packet->fromByte(pdata); 

     delete work; 
    } 
} 

這是我處理工作的代碼....我應該在這裏還是兩個地方刪除工作實例?在此先感謝...

+0

在析構函數中。 – Mankarse

回答

1

你的代碼第二位來看,它看起來像內存泄漏可能實際上是從Packet分配,因爲Work實例在什麼似乎是一個正確的位置被刪除(在workLoopaddWork)。但是我不能確定沒有看到更多的代碼。

C++中的分配沒有引用計數,因此在完成使用後應該刪除Work實例。如果你事先刪除它,它就消失了:使用該指針並且結果將是未定義的(可能工作,可能不會)。如果你不刪除它,它會泄漏(如你所見)。

你應該重構你的代碼使用智能指針 - 看的std ::的unique_ptr <>和std :: shared_ptr的<>(或升壓:: scoped_ptr的<>和boost :: shared_ptr的<>)。他們將幫助確保事情在他們真的應該被刪除時:

for(;;) 
{ 
    std::unique_ptr<int> uptr(new int); 
    std::shared_ptr<int> sptr = std::make_shared<int>(); 

    // uptr and sptr will be automatically deleted at this end of scope. 
} 
0

沒有,這是災難性的。 work指針仍在使用中,並且您正在使用它。這使它成爲一個搖晃的指針。引用一個懸掛指針是未定義的行爲

如果您不想管理對象的釋放,請使用shared_ptr<>或其他智能指針。否則,delete它們在ServerManager::~ServerManager()之內,因爲您仍將在m_workHandler之內引用它們。

1

如果要插入工作納入隊列和未完成尚未處理,你不希望在加入後立即將其刪除。

你想要做的是仔細看看你的代碼,當你不再需要你周圍的對象時刪除它。這通常是在您完成WorkHandler中的工作並將其安全地從隊列中移除之後完成的。

1

addWork()中刪除不會 - 你剛剛添加了對象,其他一些代碼可能會開始訪問它。如果你delete它現在你遇到未定義的行爲。 workLoop()是一個更好的地方 - 你已經完成了對象的所有工作,看起來不再需要,所以你可以在這裏刪除它。

1

完成該操作後,您應該釋放該對象(delete)。您不應該刪除同一個對象兩次。一旦你有delete一個對象,你不應該嘗試通過其他指針訪問它。

請記住,C++沒有任何垃圾回收。所以沒有引用計數。如果您使用newdelete,則需要手動處理自己的分配和釋放。否則,您可以使用auto_ptr

1
  1. 如果你在第一個地方刪除work你,最有可能,獲取故障試圖從指針不指向正確的對象讀取,但標準說,這是UB,所以有可能是你的程序不會崩潰。
  2. 如果您在第二位刪除work即可。

但更好的解決辦法是將work一些智能指針,這將(離開while環路workloop後,你的情況)破壞後自動刪除。爲此,使用boost::shared_ptr<>

+0

'delete'不會空指針。從已刪除的指針(並從空指針中讀取)是未定義的 - 意味着它可能會崩潰或者它可能不會。 –

+0

@Cory Nelson固定 –