Разница между malloc и calloc с помощью std :: string

Недавно я попал в C ++ и столкнулся с проблемой работы с malloc.
Приведенный ниже код не выводит «Success» (программа вылетает с кодом выхода 0xC0000005), тогда как если я использую calloc, то все работает нормально.

int main(){
std::string* pointer = (std::string*) malloc(4 * sizeof(std::string));

for(int i = 0; i < 4; i++){
pointer[i] = "test";
}

std::cout << "Success" << std::endl;

return 0;
}

Код ниже работает.

calloc(4, sizeof(std::string));

Malloc также работает, если я выделяю примерно в 12 раз больше обычной суммы.

Может кто-нибудь объяснить это поведение? Это как-то связано с std :: string?

1

Решение

std::string* pointer = (std::string*) malloc(4 * sizeof(std::string));

Это только выделяет память, достаточную для хранения 4 строковых объектов. Он не создает их, и любое использование до создания не определено.

РЕДАКТИРОВАТЬ: Что касается того, почему это работает с Calloc: скорее всего, конструктор по умолчанию std::string устанавливает все поля на ноль. Возможно, calloc просто делает то же самое, что и стандартная конструкция std :: string в вашей системе. Напротив, небольшие объекты malloc (), вероятно, размещаются с начальным мусором, поэтому объекты не находятся в допустимом состоянии.

С достаточно большой malloc() эффект похож на calloc(), когда malloc() не может повторно использовать ранее выделенный блок (с потенциальным мусором), он запрашивает новые блоки из операционной системы. Обычно ОС очищает любой блок, который она передает приложению (чтобы избежать утечки информации), заставляя большой malloc () вести себя как calloc ().

Это не будет работать на всех системах и компиляторах. Это зависит от того, как компилятор реализует std::string и зависит от того, как неопределенное поведение может запутать компилятор. Это означает, что если он работает на вашем компиляторе сегодня, он может не работать в другой системе или с новым компилятором. Хуже того, он может перестать работать в вашей системе с вашим компилятором после того, как вы отредактируете, казалось бы, не связанный код в вашей программе. Никогда не полагайтесь на неопределенное поведение.

Самое простое решение — позволить C ++ иметь дело с размещением и конструированием, а затем с уничтожением и освобождением. Это автоматически сделано

std::vector<std::string> str_vec(4);

Если вы настаиваете на выделении и освобождении вашей собственной памяти (что является плохой идеей в 99,9% случаев), вы должны использовать new скорее, чем malloc, В отличие от malloc(), с помощью new на самом деле строит объекты.

// better use std::unique_ptr<std::string[]>
// since at least it automatically
// destroys and frees the objects.
std::string* pointer = new std::string[4];

... use the pointer ...

// better to rely on std::unique_ptr to auto delete the thing.
delete [] pointer;

Если по какой-то странной причине вы все еще хотите использовать malloc (что является плохой идеей в 99,99% случаев), вы должны сами создавать и разрушать объекты:

constexpr int size = 4;
std::string* pointer = (std::string*) malloc(size * sizeof(std::string));
for (int i=0; i != size ;++i)
// placement new constructs the strings
new (pointer+i) std::string;

... use the pointer ....

for (int i=0; i != size ;++i)
// destruct the strings
pointer[i].~string();
free(pointer);
7

Другие решения

Может кто-нибудь объяснить это поведение?

Поведение не определено в обоих случаях. calloc случай, появляющийся на работу, просто из-за неудачи.

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

Самый простой способ построить динамически размещенный массив объектов — это использовать вектор:

std::vector<std::string> vec(4);
5

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector