Я записал следующий пример программы, но он отказывает с 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;
}
Я не могу выяснить, как заставить его работать. Любые идеи, если даже возможно использовать malloc()
и std::string
s?
Спасибо, Boda Cydo.
Вы не можете 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
, использованная выше, называется «размещение нового». Однако в вашем случае нет необходимости во всех этих ухищрениях.
Для класса
или 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 вы берете на себя ответственность за вызов деструктора вручную и в зависимости от источника блока памяти, передавая его владельцу.
В общем, если вы еще не знаете, что вам нужно новое место размещения, оно вам почти наверняка не понадобится. Он имеет законное использование, но есть неясные уголки рамок, а не повседневные явления.
Выделение памяти с помощью malloc
не вызывает никаких конструкторов. Не смешивайте распределение в стиле C с объектами C ++ . Они плохо играют вместе. Вместо этого используйте оператор new
для выделения объектов в коде C ++:
example *ex = new example;
Это более умный код, который вызовет конструктор std :: string :: string ()
для инициализации строки , который исправит наблюдаемый вами segfault. И не забудьте удалить его, когда закончите, чтобы освободить память и вызвать соответствующие деструкторы:
delete ex;
вы не должны использовать
example * ex = (example *) malloc (sizeof (* ex));
, потому что то, что возвращает sizeof (* ex), равно размеру long или размеру int, что связано с различным окружением компиляции. вы можете использовать следующий код:
example * ex = (example *) malloc (sizeof (пример));
Проблема в том, что malloc
не вызывает конструктор примера
. Поскольку строка
обычно представляется как указатель в стеке, она устанавливается в ноль, и вы разыменовываете нулевой указатель. Вместо этого вам нужно использовать новый
.