使用动态内存分配创建的包含字符串值的结构体在赋值时会导致分段错误

7
编译器在以下代码上抛出运行时段错误:
#include <iostream>
#include <string>
using namespace std;

struct Node{
  int data;
  void *next;   
  string nodeType;
};

Node* initNode(int data){
  Node *n = (Node*)malloc(sizeof(Node));
  n->data = data;
  n->next = NULL;
  n->nodeType = "Node";   //if this line is commented it works else segfault
  return n;
}

int main() {
  Node *n1 = initNode(10);
  cout << n1->data << endl;
}

请问为什么在动态分配的结构体中字符串赋值不起作用,而在静态分配的情况下却可以?

以下是有效的方法:

Node initNode(string data){
  Node n;
  n.data = data;  //This works for node creation statically
  n.next = NULL;
  n.nodeType = "Node";  //and even this works for node creation statically
  return n;
}

在主函数中添加如下代码:
int main() {
  Node n2 = initNode("Hello");
  cout << n2.data << endl;
}

1
malloc 只是分配内存,它不会 构造 对象实例,这意味着 string 构造函数不会被调用。 - Some programmer dude
3
通常的经验法则是:在C++中不要使用C的malloc,而应该使用new,如果可能的话也不要使用new,可以使用make_sharedstd::unique_ptr(C++11)。注意不改变原意。 - Félix Cantournet
4个回答

8

这种方法行不通,因为你没有真正地在内存中构造一个Node实例,而只是malloc了一块内存。

你应该使用new代替malloc

Node *n = new Node{};

malloc只分配内存,它不知道什么是类或如何实例化一个类。在C++中通常不应该使用它。

new分配内存构造一个类的实例。


嘿,这个可以用: Node *n = new Node();但我认为malloc实际上会通过创建实例来分配内存?这是真的吗?你能否解释一下或提供使用“new”和“malloc”的区别以及何时使用它的指针? - Dhwanit
没错!谢谢!其实我有一种感觉,当我使用malloc时,字符串的构造函数会被调用,因为它是一个字符串而不是字符串指针。 - Dhwanit
malloc 不会调用你类的任何成员的构造函数。 - TartanLlama

4

没有任何地方执行std::string构造函数。

您应该使用new关键字

example *e = new example;

或者使用放置new。
void *example_raw = malloc(sizeof(example));
example *e = new(example_raw) example;

3
 Node *n = (Node*)malloc(sizeof(Node));

这段代码是胡说八道的。你不能只是告诉编译器假装一块刚分配的数据包含一个合法的 Node 对象,然后操作它。


没错!其实我有一种感觉,当我使用malloc时,字符串的构造函数会被调用,因为它是一个字符串而不是一个字符串指针在节点内部。 - Dhwanit

1

string在C++中是一个类,要创建字符串对象,使用new,而不是像下面这样使用malloc

Node *n = new Node{};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接