Возможная утечка памяти с помощью malloc, struct, std :: string и free - PullRequest
2 голосов
/ 30 сентября 2011

У меня есть ситуация, подобная следующей, и я не уверен, утекли ли элементы std :: string памяти struct или это нормально.Память, выделяемая этими двумя std :: strings, удаляется при вызове free(v)?

struct MyData
{
    std::string s1;
    std::string s2;
};

void* v = malloc(sizeof(MyData));

...

MyData* d = static_cast<MyData*>(v);
d->s1 = "asdf";
d->s2 = "1234";

...

free(v);

Утечка или нет?

Я использую void-указатель, потому что у меня есть другая улучшенная структура, которая состоит из enum и void-указателя.В зависимости от значения переменной enum, void * будет указывать на различные структуры данных.

Пример:

enum-field имеет EnumValue01 => указатель void будет указывать на malloc'd MyData01 struct

enum-field имеет EnumValue02 => void-указатель будет указывать на malloc'd MyData02 struct

Предложения для разных подходов очень приветствуются, конечно.

Ответы [ 6 ]

4 голосов
/ 30 сентября 2011

Вы не должны использовать malloc() и free() в программе на C ++; они не осведомлены о конструкторе / деструкторе.

Используйте операторы new и delete.

4 голосов
/ 30 сентября 2011

Это неопределенное поведение - память, выделенная malloc() в неинициализированном виде, поэтому использование ее в качестве структуры, содержащей string объектов, может привести к чему угодно;Я бы ожидал сбой.Поскольку никто не вызывает деструктор перед вызовом free(), объекты string не будут уничтожены, а их буферы почти наверняка утекут.

2 голосов
/ 30 сентября 2011

Действительно, есть утечка. free не вызывает деструктор MyData (в конце концов, это функция C, которая ничего не знает о C ++). Либо вы должны использовать new / delete вместо malloc / free:


MyData* d = new MyData;
d->s1 = "asdf";
d->s2 = "1234";
delete d;

или вызовите деструктор самостоятельно:


void* v = malloc(sizeof(MyData));
MyData* d = new (v) MyData; // use placement new instead of static_cast
d->s1 = "asdf";
d->s2 = "1234";
...
d->~MyData();
free(v);

Как отметил Шипот, вы не можете напрямую использовать память, выделенную malloc, как структуру MyData без инициализации, так что вы должны сделать это и сами. Чтобы инициализировать MyData с использованием уже выделенной памяти, вам нужно использовать новое размещение (см. Код выше).

2 голосов
/ 30 сентября 2011

Да, потому что конструктор и деструктор не вызываются. Используйте new и delete.

1 голос
/ 30 сентября 2011

Да, вы, вероятно, протекаете, и ваши строки тоже не правильно построены.Поведение программы не определено, что означает, что все пойдет не так.

Ближайший действительный способ сделать то, что вы делаете, это размещение new.Тем не менее, вам лучше использовать некоторый общий базовый класс и правильный полиморфизм C ++.

Если возможные типы не связаны, вы можете использовать Boost.Any или Boost.Variant.

1 голос
/ 30 сентября 2011

Даже если вам удастся правильно инициализировать s1 и s2, простое выполнение free (d) не освободит память, динамически выделенную для s1 и s2.Вы действительно должны создать * d с помощью new и уничтожить с помощью delete, что обеспечит надлежащее уничтожение s1 и s2 (а также инициализацию).

...