当 malloc()-ing 相同的结构时,如何在结构中使用 C++ 字符串?
Posted
技术标签:
【中文标题】当 malloc()-ing 相同的结构时,如何在结构中使用 C++ 字符串?【英文标题】:How to use a C++ string in a structure when malloc()-ing the same structure? 【发布时间】:2011-03-25 14:51:04 【问题描述】:我编写了以下示例程序,但它因段错误而崩溃。问题似乎在于在结构中使用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;
我不知道如何使它工作。如果可以使用malloc()
和std::string
s,有什么想法吗?
谢谢,博达·赛多。
【问题讨论】:
【参考方案1】:你不能 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
的形式称为“放置新”。但是,在您的情况下,不需要所有这些诡计。
【讨论】:
我使用 malloc() 因为 new 抛出异常而不是返回 NULL。我只是不想在那部分代码中出现异常。该代码发生在 C 回调中,我不想在 C 回调中引发 C++ 异常。所以我使用了malloc。对此有什么想法吗? @bodacydo:您可以使用new(std::nothrow) example
以使new
返回空指针而不是抛出异常。您必须包含标题 <new>
才能使用 std::nothrow
常量。
@bodacydo:如果您真的希望new
在失败时返回空指针,请使用new(nothrow) example
。但实际上你应该只使用try
/catch
来捕获任何抛出的异常。 (例如,std::string
分配如果分配内存失败也可能引发异常。)
这非常有用,因为我使用的库要求我对传递到其函数调用的对象使用他们的自定义 alloc 命令,但没有提供使用它的方法及其包含非平凡结构的结构的派生。很好的答案!【参考方案2】:
对于class
或struct
,例如您的example
,正确答案是使用new
而不是malloc()
来分配实例。只有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,您有义务提供正确大小和对齐方式的内存区域。不提供正确的尺寸或对齐方式会导致神秘的事情出错。不正确的对齐通常会更快导致问题,但也可能很神秘。
另外,对于一个新的放置,您负责手动调用析构函数,并根据内存块的来源,将其释放给它的所有者。
总而言之,除非您已经知道您需要一个新的展示位置,否则您几乎肯定不需要它。它有合法的用途,但有一些框架的模糊角落,而不是日常发生的事情。
【讨论】:
从来没有听说过这些。谢谢!【参考方案3】:使用malloc
分配内存不会调用任何构造函数。 不要将 C 风格的分配与 C++ 对象混用。他们一起玩得不好。而是使用 new
运算符在 C++ 代码中分配对象:
example *ex = new example;
这是更智能的代码,它将调用std::string::string()
构造函数来初始化字符串,这将修复您看到的段错误。当你完成释放内存并调用适当的析构函数时,不要忘记删除它:
delete ex;
【讨论】:
【参考方案4】:问题是malloc
没有调用example
的构造函数。由于 string
通常表示为堆栈上的指针,因此将其设置为零,并且您取消引用空指针。您需要改用new
。
【讨论】:
【参考方案5】:你不应该使用
示例 *ex = (示例 *)malloc(sizeof(*ex));
因为 sizeof(*ex) 返回的大小等于 long 的大小或 int 的大小,这是由于您的编译环境不同。 您可以使用如下代码:
示例 *ex = (示例 *)malloc(sizeof(example));
【讨论】:
如果你不小心,有人会否决这个(因为这是错误的)。以上是关于当 malloc()-ing 相同的结构时,如何在结构中使用 C++ 字符串?的主要内容,如果未能解决你的问题,请参考以下文章
malloc 和 free 在 C 中是如何实现的? [复制]