Подтвердить что ты не робот

Как использовать строку С++ в структуре, когда malloc() - с той же структурой?

Я написал следующую примерную программу, но она сработала с segfault. Проблема заключается в использовании malloc и std::string в структуре.

#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?

Спасибо, Бода Сидо.

4b9b3361

Ответ 1

Вы не можете malloc класс с нетривиальным конструктором в С++. То, что вы получаете от malloc, представляет собой блок необработанной памяти, который не содержит правильно построенный объект. Любые попытки использовать эту память как "реальный" объект не сработают.

Вместо объекта malloc -ing используйте new

example *ex = new example;

Ваш исходный код может быть принудительно работать с malloc, используя следующую последовательность шагов: malloc необработанная память сначала, постройте объект в этой необработанной ячейке памяти:

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

Используемая форма new называется "размещение нового". Тем не менее, в вашем случае нет необходимости во всех этих трюках.

Ответ 2

Для class или struct, таких как ваш example, правильным ответом является использование new not malloc() для размещения экземпляра. Только operator new знает, как вызвать конструкторы для struct и его членов. Ваша проблема вызвана тем, что элемент строки не был сконструирован.

Однако существуют случаи редкие, когда важно, чтобы определенный патч памяти действовал так, как если бы он содержал экземпляр класса. Если у вас действительно такой случай, тогда существует вариант operator 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

Используя новое место размещения, вы обязаны предоставить область памяти правильного размера и выравнивания. Не предоставление правильного размера или выравнивания приведет к таинственным вещам. Неправильное выравнивание обычно быстрее вызывает проблему, но также может быть загадочным.

Кроме того, с новым местом размещения вы берете на себя ответственность за вызов деструктора вручную и в зависимости от происхождения блока памяти, освобождая его его владельцу.

В целом, если вы уже не знаете, что вам нужно новое место, вам почти наверняка не нужно. Он имеет законное использование, но есть неясные углы фреймворков, а не повседневные события.

Ответ 3

Выделение памяти с помощью malloc не вызывает никаких конструкторов. Не смешивать выделение C-стиля с объектами С++. Они не играют хорошо вместе. Вместо этого используйте оператор new для размещения объектов в коде С++:

example *ex = new example;

Это более разумный код и вызовет конструктор std::string::string() для инициализации строки, которая будет фиксировать segfault, который вы видите. И не забудьте удалить его, когда вы закончите, чтобы освободить память и вызвать соответствующие деструкторы:

delete ex;

Ответ 4

Проблема заключается в том, что malloc не вызывает конструктор example. Так как a string обычно представляется как указатель на стек, это устанавливается равным нулю, и вы разыскиваете нулевой указатель. Вместо этого вам нужно использовать new.

Ответ 5

вы не должны использовать

example * ex = (пример *) ТаНос (SizeOf (* ех));

потому что возвращаемое значение sizeof (* ex) равно размеру long или size int, что обусловлено тем, что вы окружаете разные компиляции. вы можете использовать следующий код:

example * ex = (пример *) ТаНос (SizeOf (пример));