Как использовать строку C++ в структуре когда 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 = "hello world";
 std::cout << ex->data << std::endl;
}

Я не могу выяснить, как заставить его работать. Любые идеи, если даже возможно использовать malloc() и std::strings?

Спасибо, Boda Cydo.

16
задан Kirill V. Lyadvinsky 5 August 2010 в 04:59
поделиться

5 ответов

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

26
ответ дан 30 November 2019 в 16:57
поделиться

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

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

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

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

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

4
ответ дан 30 November 2019 в 16:57
поделиться

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

example *ex = new example;

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

delete ex;
3
ответ дан 30 November 2019 в 16:57
поделиться

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

example * ex = (example *) malloc (sizeof (* ex));

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

example * ex = (example *) malloc (sizeof (пример));

0
ответ дан 30 November 2019 в 16:57
поделиться

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

2
ответ дан 30 November 2019 в 16:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: