Добрый день. Есть код: Код (Text): typedef struct{ std::string obj1; // stl-ный string int m; } TMYSTR; int main(int argc, char* argv[]) { TMYSTR *pp=(TMYSTR*)calloc(sizeof(TMYSTR),1); pp->obj1="hello"; free(pp); } VC6 Такой код отлично работает, хотя выделение по правилам нужно делать с помощью new. Поясните пожалуйста, как происходит выделение памяти под объект string в данном случае? В момент calloc память еще не выделяется, а в момент присваивания строки hello выделяется памяти и происходит копирование. Это выполняется с помощью конструктора копии? Заранее благодарен за ответы.
typedef struct{ std::string obj1; // stl-ный string int m; } TMYSTR; Фейспалм. Почему структура в стиле си, а внутренности - си++? То, что он работает - это всего лишь случайность. В общем случае это работать не должно.
Вот потому и вызывает удивление, что работать не должен, однако - работает. Интересны internals такого поведения. Видимо создается временный объект string, а после успешно присваивается.
Работает потому-что calloc инициализирует память нулём и потому-что так легла карта, не факт что объект должен инициализироваться нулями. Память под объект выделяется, все внутренние структуры объекта установлены в достаточно безопасное значение - ноль.
место в котором должно бы падать - конструктор копии std::string (pp->obj1="hello" Почему не падает - х.з. - наверное можно увидеть в исходниках std. Может быть не обращается к внутренним данным, или обращается, но данные NULL (после calloc) и ничего плохого с ними не происходит. В подобных случая говорят что поведение не определено, то есть может произойти ВСЕ ЧТО УГОДНО. В том числе что-нибудь хорошее ожидаемое и полезное
Mentor Это не конструктор копий, а оператор присваивания. У стринга есть статический буфер небольшого размера, а если бы и не было, то все структуры установлены в ноль, упасть скорее не должно, чем должно.
mitsrc это еще можете подебажить выделяется память в куче вызывается для нее конструктор потом через функцию выводится тип и освобождается память Код (Text): #define ctor(t) \ (new(HeapAlloc(GetProcessHeap(), 0, sizeof((t))))t) template<class T> inline void dtor(T *h){ if (h) HeapFree(GetProcessHeap(), 0, (h->~T(),h)); } int main(){ int *p = ctor(int(0xdeadc0de)); dtor(p); std::string *s = ctor(std::string("content")); dtor(s); }
Выделять память через calloc скорее всего безопасно, поскольку в "нормальных"=неэкзотических реализациях std::string конструктор по умолчанию наверняка просто зануляет структуру string, и calloc делает то же самое. А вот простой вызов free без явного вызова деструктора string будет приводить к утечке памяти (даже для коротких строк, т.к. далеко не все реализации хранят короткие строки в самой string)
сплошные гадания и имена. прям как на форуме вб. что стоит скомпилить этот кусочек с дебуг инфой и посмотреть как оно в дебуге/дизасме. все вопросы сами собой отпадут.