C++ 如何使用C++;当malloc()调用同一结构时,是否在结构中使用字符串?

C++ 如何使用C++;当malloc()调用同一结构时,是否在结构中使用字符串?,c++,string,struct,malloc,C++,String,Struct,Malloc,我编写了下面的示例程序,但它因segfault而崩溃。问题似乎在于在结构中使用malloc和std::strings #include <iostream> #include <string> #include <cstdlib> struct example { std::string data; }; int main() { example *ex = (example *)malloc(sizeof(*ex)); ex->data =

我编写了下面的示例程序,但它因segfault而崩溃。问题似乎在于在结构中使用
malloc
std::string
s

#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;
}
#包括
#包括
#包括
结构示例{
std::字符串数据;
};
int main(){
示例*ex=(示例*)malloc(sizeof(*ex));
ex->data=“你好世界”;

STD::CUDATABLE < P>不能使用C++中的非平凡构造函数编写代码> MalOC/<代码>。从代码> MaloC/<代码>中得到的是一个原始内存块,它不包含正确构造的对象。任何试图将该内存用作“真实”对象的尝试都会失败。 使用
new

example *ex = new example;
您的原始代码也可以通过使用以下步骤序列强制使用
malloc
malloc
raw memory首先,然后在该raw memory中构造对象:

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

上面使用的
new
形式称为“placement new”但是,在你的情况下不需要所有的欺骗。分配内存>代码> MalOC/不调用任何构造函数。<强>不要将C样式分配与C++对象< /强>混合。它们不能很好地配合。相反,使用<代码>新< /Cord>运算符在C++代码中分配对象:

example *ex = new example;
这是一个更智能的代码,它将调用
std::string::string()
构造函数来初始化字符串,这将修复您看到的segfault。当您释放内存并调用相应的析构函数时,不要忘记删除它:

delete ex;

问题是
malloc
不调用
示例的构造函数。由于
字符串
通常表示为堆栈上的指针,因此将其设置为零,然后取消对空指针的引用。您需要使用
新建

对于
结构
,例如
e例如
,正确答案是使用
new
而不是
malloc()
分配实例。只有
operator new
知道如何调用
struct
及其成员的构造函数。您的问题是由从未构造过的字符串成员造成的

然而,也有罕见的情况,在这种情况下,一个特定的内存补丁的行为就好像它持有一个类的实例一样是很重要的。如果你真的有这样的情况,那么就有一个
操作符new
的变体,允许指定对象的位置。这叫做a,必须非常小心地使用

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,您有义务提供大小和对齐方式正确的内存区域。不提供正确的大小或对齐方式会导致神秘的事情出错。不正确的对齐方式通常会更快地导致问题,但也可能是神秘的

另外,对于一个新的位置,您负责手动调用析构函数,并根据内存块的来源将其释放给其所有者

总之,除非你已经知道你需要一个新的位置,否则你几乎肯定不需要它。它有合法的用途,但框架中有一些模糊的角落,而不是每天都会出现。

你不应该使用它

示例*ex=(示例 *)malloc(sizeof(*ex))

因为sizeof(*ex)返回的值等于long的大小或int的大小,这是因为编译环境不同。 您可以按如下方式使用代码:

示例*ex=(示例 *)malloc(sizeof(示例))


我使用MalCube(),因为新抛出异常而不是返回null。我只是不希望代码中的异常发生。代码发生在C回调中,我不想在C回调中抛出C++异常。所以我使用Maloc。有什么想法吗?@ BooCydodo:您可以使用<代码> new(STD:NoFrPoT)。示例
为了使
new
返回空指针,而不是抛出异常。您必须包含头
才能使用
std::nothrow
常量。@bodacydo:如果您确实想
new
在失败时返回空指针,请使用
new(nothrow)示例
。但实际上,您应该只使用
try
/
catch
来捕获任何抛出的异常。(例如,
std::string
赋值如果分配内存失败,也可能抛出异常。)这是非常有用的,因为我使用的库要求我对传递到函数调用中的对象使用自定义alloc命令,但没有提供将其用于包含非平凡结构的结构派生的方法。回答得很好!从未听说过这些。谢谢!如果你不小心,有人会投反对票的(因为这是错误的)。