Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.09.2013, 00:18   #1
retrix147
 
Регистрация: 25.09.2010
Сообщений: 9
Вопрос Динмическое выделение памяти под строку

Вот у меня есть 2 примера:

Код:
char* str = "Немыслимый текст";
char* s = new char [strlen(str)+1]
Тут указатель s будет указывать на блок в памяти, который по размеру равен строке, на которую указывает указатель str и +1 символ для нулевого символа.

Код:
char* str = new char;
std::cin>>str;
А вот под что выделяется память так? Хоть такое и работает но я не могу понять на какой блок памяти будет указывать указатель str с самого начала и почему он способен вместить то, что в него запишут после инициализации?
retrix147 вне форума Ответить с цитированием
Старый 22.09.2013, 10:23   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Выделяет память для одного символа char.
Собственно так НЕ работает, блок НЕ способен вместить то, что в него запишут - просто запись идет в чужпй блок памяти и в реальной программе это будет портить данные.
waleri вне форума Ответить с цитированием
Старый 22.09.2013, 19:51   #3
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Код:
type* ptr = new type; //<--- выделяем блок памяти
//который не меньше sizeof(type)
Размер выделенного блока может быть больше, чем запрошенный, но гарантированно не меньше.

Память будет инициализирована дефолтным конструктором type

ptr - указывает на начало этого блока

Код:
type* ptr = new type[NUMBER]; //<--- выделяем блок памяти
//который не меньше sizeof(type)*NUMBER
Размер выделенного блока гарантированно сможет вместить в себя NUMBER объектов типа type

То есть он будет не меньше, чем sizeof(type)*NUMBER, но может быть больше.

Реально, обычно выделяется sizeof(type)*NUMBER+sizeof(size_t)

Все эти объекты будут расположены друг за другом, и проинициализированны дефолтным конструктором type

ptr - хранит адрес первого элемента

Код:
char* str = new char; //<--- запросили блок, sizeof(char)
//то есть, запросили блок под один единственный элемент типа char

std::cin>>str; //<--- записываем по адресу блока данные из ввода
Может вместить в себя один символ, но если их будет больше одного - переполнение буфера (порча памяти)
_Bers вне форума Ответить с цитированием
Старый 23.09.2013, 22:48   #4
retrix147
 
Регистрация: 25.09.2010
Сообщений: 9
По умолчанию

Но ведь все работает, или нет? Как мне считать строку из клавиатуры, неизвестной длины без потери памяти при помощи указателя тогда?

Хотя у меня такое чувство, что я чего-то уж сильно не понимаю...
Т.е. можно еще разок объяснить как работает то что я написал, только попроще...
Изображения
Тип файла: jpg 6.jpg (23.2 Кб, 187 просмотров)
Тип файла: jpg 5.jpg (31.7 Кб, 182 просмотров)

Последний раз редактировалось retrix147; 24.09.2013 в 00:07.
retrix147 вне форума Ответить с цитированием
Старый 24.09.2013, 08:31   #5
Ezhik Kihze
Форумчанин
 
Регистрация: 24.12.2012
Сообщений: 639
По умолчанию

Цитата:
Но ведь все работает, или нет?
Работает потому что new выделяет память чуть больше + за указателем не было критичных данных + воля случая....
ICQ: 677936656 Gmail: ekEmbed@gmail.com
Ezhik Kihze вне форума Ответить с цитированием
Старый 24.09.2013, 16:31   #6
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от retrix147 Посмотреть сообщение
Но ведь все работает, или нет?
Это случай, когда говорят: лучше бы вообще не работало.
Мина замедленного действия.

Последствия не предсказуемы.

Отказ может произойти в любой момент.

Записывая левые данные за пределами буфера, можно запросто повредить другие узлы системы.

То есть, в будущем может произойти сбой очень далеко от истинного места аварии.


Подобные ошибки иногда очень сложно отлавливать. И это отравляет жизнь.

Цитата:
Сообщение от retrix147 Посмотреть сообщение
Как мне считать строку из клавиатуры, неизвестной длины без потери памяти при помощи указателя тогда?
В твоем случае - никак.
_Bers вне форума Ответить с цитированием
Старый 25.09.2013, 16:42   #7
Гром
Старожил
 
Аватар для Гром
 
Регистрация: 21.03.2009
Сообщений: 2,193
По умолчанию

Цитата:
Но ведь все работает, или нет?
Представьте, что считываемая строка - это гвоздь, а выделенная память - стенка. В некоторых случаях вам может сойти с рук, если вы будете помещать гвоздь к недостаточно объемную стенку - острие просто будет торчать с другой стороны, находясь там на нелегальном положении. Но однажды с той стороны стенки может оказаться чья-то голова (не относящиеся к нашему гвоздю данные)...
Цитата:
Как мне считать строку из клавиатуры, неизвестной длины без потери памяти при помощи указателя тогда?
Если пользователь может ввести строку неизвестной заранее длины - считывайте данные по частям (например, через istream::getline) фиксированной длины и пока не считаете все до конца - динамически расширяйте результирующую строку и добавляйте к ней вновь считанные фрагменты.
Простые и красивые программы - коды программ + учебник C++
Создание игры - взгляд изнутри - сайт проекта
Тема на форуме, посвященная ему же
Гром вне форума Ответить с цитированием
Старый 25.09.2013, 17:02   #8
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Гром Посмотреть сообщение
Если пользователь может ввести строку неизвестной заранее длины -
Код:
#include <iostream>
using namespace std;

#include <iostream>

int main()
{
	std::cout << "Hello, World!" << std::endl;
  
  std::string date;
  
  std::cin>>date;
  

}
_Bers вне форума Ответить с цитированием
Старый 25.09.2013, 17:34   #9
Гром
Старожил
 
Аватар для Гром
 
Регистрация: 21.03.2009
Сообщений: 2,193
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Код:
#include <iostream>
using namespace std;

#include <iostream>

int main()
{
	std::cout << "Hello, World!" << std::endl;
  
  std::string date;
  
  std::cin>>date;
  

}
Вот помнил же я, что есть в STL что-то автоматическое под этот вопрос!

Ну а вообще - совет мой именно для работы с сишными строками, если уж так нужно именно их использовать. Если не обязательно - то std::string таки рулит.
Простые и красивые программы - коды программ + учебник C++
Создание игры - взгляд изнутри - сайт проекта
Тема на форуме, посвященная ему же
Гром вне форума Ответить с цитированием
Старый 25.09.2013, 17:54   #10
Rififi
Старожил
 
Регистрация: 19.08.2009
Сообщений: 2,119
По умолчанию

retrix147

Как мне считать строку из клавиатуры, неизвестной длины без потери памяти при помощи указателя тогда?

как-то так...

Код:
char ch;
char* s = NULL;	

for (size_t count = 1; (ch = _getch()) != '\r'; count++)
{
	s = (char*) realloc(s, (count + 1) * sizeof(char));
	s[count - 1] = ch;
	s[count] = 0;
	
	_putch(ch);
}

free(s);
Rififi вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
выделение памяти под двумерный массив Felixjkee Помощь студентам 0 09.01.2013 11:25
выделение памяти под динамически массив Дмитрий Ас Помощь студентам 0 22.12.2012 01:39
Выделение памяти под структуру. Си Vitany Помощь студентам 0 05.12.2012 17:50
выделение памяти под объект VIK_aka_TOR Общие вопросы Delphi 4 15.02.2012 19:20
выделение памяти под массив на C Kingdom_Reborn Помощь студентам 12 12.01.2011 04:40