C Создание массива с переменной в качестве длины генерирует массив случайного размера

#c #arrays #pointers

#c #массивы #указатели

Вопрос:

Я воссоздаю класс string, используя массивы char. Моя проблема в том, что когда я выделяю память для большего массива, он генерирует массив совершенно неправильного размера.

Например:

 int allocated = 4;
char * reservedString = new char[allocated];
cout << strlen(reservedString);
  

Вместо создания массива символов размером 4, reservedString указывает на массив символов с 14 ячейками, содержащими случайные символы.

введите описание изображения здесь

Это то, что показывает мне отладка. Зарезервированная строка теперь имеет неправильный размер с кучей случайных символов в ней. Когда я пытаюсь использовать strcpy или strcpy_s, это выводит память за пределы, потому что новые размеры массива неправильные.

Как я могу создать массив символов с неизвестной длиной, которая обеспечивается переменной правильного размера. Я не могу использовать std::string class или std::vector.

Комментарии:

1. Вы хотите использовать std::vector или std::string .

2. Я бы сделал, если бы мог, но это для проекта класса, и я не могу использовать векторы или строки, только массивы.

3. Читайте здесь: cplusplus.com/reference/cstring/strlen . Функция выполняет поиск символа завершения. Ваша строка неинициализирована.

4. Вы не инициализируете свой массив, поэтому он содержит случайный мусор. Как отметил Chiel, strlen будет искать null-terminator, он не может знать, сколько байтов вы выделили.

5. Нет, потому что вы записываете один символ после конца выделенной памяти, а также strlen пытаетесь прочитать неинициализированные значения в середине массива — это неопределенное поведение (насколько мы знаем, там может просто оказаться нулевой символ). Вам необходимо правильно инициализировать весь ваш массив. Почему вам в любом случае нужно определять размер вновь выделенного массива с помощью strlen ? Если вы не собираетесь помещать в него строку, заканчивающуюся нулем, вам следует отслеживать ее размер.

Ответ №1:

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

В документации о strlen говорится:

вычисляет длину строки str с точностью до, но не включая завершающий нулевой символ.

Здесь нет нулевого ограничителя.

Вы должны сделать:

 int allocated = 4;
char * reservedString = new char[allocated]();
  

Это инициализирует ваш массив и установит все элементы в

Комментарии:

1. Поскольку для каждого элемента установлен завершающий нулевой символ, strlen вернет 0, но я могу отслеживать размер самостоятельно. С точки зрения памяти, даже если strlen возвращает 0, потому что первый символ теперь является нулевым завершающим символом, по-прежнему ли он резервирует 4 байта памяти?

2. @EmptyStuff вы правы, память была выделена правильно. Теперь вы можете проверять размер должным образом каждый раз, когда вы изменяете строку, вам просто нужно отслеживать размер.

3. @EmptyStuff Да. strlen выдает длину строки, заканчивающейся нулем, которая может отличаться от размера массива, используемого для хранения строки.

4. @mohabouje Или просто правильно завершите его обнулением. Строковые функции должны обрабатывать остальное, пока массив достаточно велик.

5. @FeiXiang не могли бы вы пояснить, что вы подразумеваете под правильным завершением его нулем.

Ответ №2:

strlen ожидает строку, заканчивающуюся нулем, что означает строку, которая заканчивается нулевым символом ( ). Вы передаете ему указатель, указывающий на недавно выделенную память, которая содержит неинициализированные значения, и его чтение вызывает неопределенное поведение. Поэтому, когда strlen выполняется поиск символа null для определения длины строки, что-то идет не так.

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