2010-08-05 89 views
12

我寫了下面的示例程序,但它崩潰與段錯誤。問題似乎是在結構中使用mallocstd::string如何在malloc()結構中使用C++字符串?

#include <iostream> 
#include <string> 
#include <cstdlib> 

struct example { 
std::string data; 
}; 

int main() { 
example *ex = (example *)malloc(sizeof(*ex)); 
ex->data = "hello world"; 
std::cout << ex->data << std::endl; 
} 

我想不出如何使它工作。任何想法,如果它甚至可以使用malloc()std::string s?

謝謝,Boda Cydo。

回答

22

你不能在malloc中使用C++中的非平凡構造函數。你從malloc得到的是一塊原始內存,它沒有包含正確構造的對象。任何將該內存用作「真實」對象的嘗試都將失敗。

代替malloc -ing對象,使用new

example *ex = new example; 

你的原碼可被迫與malloc工作,以及,通過使用以下步驟順序:malloc原始內存第一,構造對象在原始內存第二:

void *ex_raw = malloc(sizeof(example)); 
example *ex = new(ex_raw) example; 

上面使用的new的形式被稱爲「放置新的」。但是,在你的情況下,沒有必要這麼做。

+0

我正在使用malloc(),因爲新引發異常而不是返回NULL。我只是不希望在那部分代碼中出現異常。該代碼發生在C回調中,我不想在C回調中拋出C++異常。所以我用malloc。有關於此的任何想法? – bodacydo 2010-08-05 06:09:37

+1

@bodacydo:您可以使用'new(std :: nothrow)示例'來使'new'返回空指針而不是拋出異常。你必須包含頭文件''來使用'std :: nothrow'常量。 – AnT 2010-08-05 06:20:19

+1

@bodacydo:如果你真的想'new'在失敗時返回一個空指針,使用'new(nothrow)example'。但是真的,你應該使用'try' /'catch'來捕獲拋出的異常。 (例如,'std :: string'賦值,如果分配內存失敗,也可能會拋出異常。) – jamesdlin 2010-08-05 06:22:13

2

malloc分配內存不會調用任何構造函數。 不要將C風格的分配與C++對象混合使用。他們在一起打球不好。相反,使用new運營商在C++代碼分配對象:

example *ex = new example; 

這是聰明的代碼並調用std::string::string()構造函數初始化字符串,將解決你所看到的段錯誤。而且不要忘記刪除它,當你完成釋放內存並調用相應的析構函數:

delete ex; 
2

的問題是,malloc不叫的example構造。由於string通常表示爲堆棧上的指針,因此將其設置爲零,並且您將取消引用空指針。您需要改用new

3

對於classstruct如您example,正確的答案是使用newmalloc()分配一個實例。只有operator new知道如何調用struct及其成員的構造函數。你的問題是由於字符串成員沒有被構造過。

但是,有罕見情況下重要的是一個特定的內存補丁行事,就像它擁有一個類的實例。如果你真的有這種情況,那麼operator new的變化是允許指定對象的位置。這被稱爲"placement new",必須非常小心使用。

void *rawex = malloc(sizeof(example)); // allocate space 
example ex = new(rawex) example();  // construct an example in it 
ex->data = "hello world";    // use the data field, not no crash 
// time passes 
ex->~example();       // call the destructor 
free(rawex);       // free the allocation 

通過使用placement new,您有義務提供正確大小和對齊的內存區域。不提供正確的尺寸或對齊將導致神祕的事情出錯。不正確的對齊通常會導致問題更快,但也可能很神祕。

此外,隨着放置位置的增加,您將負責手動調用析構函數,並根據內存塊的原點將其釋放給其所有者。總而言之,除非你已經知道你需要一個新的位置,你幾乎肯定不需要它。它有合法的用途,但框架的角落不明確,而不是每天發生。

+0

從來沒有聽說過任何這個。謝謝! – bodacydo 2010-08-05 06:12:45

0

你不應該使用

例如* EX =(例如 *)malloc的(的sizeof(* EX));

因爲什麼sizeof(* ex)返回等於long的大小或int的大小,這是由於你不同的編譯環境。 可以使用代碼如下:

示例* EX =(實施例 *)malloc的(的sizeof(實施例));

+0

生成大小的任何一種方法都可以使用。 – 2010-08-05 05:35:41

+0

如果你不小心,有人會投票贊成(因爲它是錯誤的)。 – 2010-08-05 07:48:59