Распределение динамической памяти для указателя char

У меня странная проблема, связанная с выделением динамической памяти для указателя char. У меня есть что-то вроде

char *input = new char; //1
gets(input) //2
char *dest = new char; //3

во время шага 3 я получаю ошибку повреждения кучи во время выполнения. Это происходит только в том случае, если длина вводимой мной строки превышает 23 символа.

Если я не буду выполнять никаких новых операций, значит, проблем нет.

Эта проблема будет решена, если я укажу

 char *input = new char[100]; 

Но я хочу, чтобы ввод был динамическим на основе ввода пользователя.

Я не уверен, какова роль в этом случае 24 байтов. Я не хочу ограничиваться 100 или несколькими n символами ... Я немного слаб в распределении памяти ... Может кто-нибудь объяснить этот сценарий?


person Kartikkumar Rao    schedule 24.12.2012    source источник
comment
Вы выделяете достаточно места только для одного персонажа. Затем вы сохраняете большее количество символов в слишком маленьком пространстве. Это просто сломано.   -  person David Schwartz    schedule 24.12.2012


Ответы (5)


Нет, так нельзя. Вы можете использовать только статический буфер или использовать «cpp-way», то есть:

std::string str;
std::getline(std::cin, str);
person kassak    schedule 24.12.2012

Ваша программа демонстрирует неопределенное поведение при вводе любой длины больше нуля, потому что gets добавляет нулевой терминатор. То, что программа не вылетает до 23 символов - досадное совпадение.

Если вы хотите, чтобы буфер распределялся динамически, не используйте ввод на основе gets или char; вместо этого считайте свои данные в std::string.

person Sergey Kalinichenko    schedule 24.12.2012
comment
Это просто совпадение, потому что я могу воспроизвести эту проблему и на других машинах ... - person Kartikkumar Rao; 24.12.2012
comment
@ karthikkumar24 Безусловно, это так: реализация new в вашем компиляторе дает вам 24 байта, когда вы запрашиваете только один, как способ уменьшить фрагментацию. В разных компиляторах дополнительный размер будет отличаться и потенциально может быть равен нулю. Стандарт запрещает вам читать или писать за пределами выделенной границы, поэтому теоретически программа может аварийно завершить работу, даже если вы читаете один символ. Подобные ошибки трудно найти, потому что очень часто программа не дает сбоев (поэтому я назвал это досадным совпадением). Чтобы обнаружить подобные ошибки, вам понадобится valgrind. - person Sergey Kalinichenko; 24.12.2012

Если вы не знаете, какую длину вводит пользователь, и не хотите ограничивать ввод данных пользователем, вам необходимо выделить достаточную длину буфера. Вы можете использовать строку STL, но она также выделяет достаточно памяти для вас динамически, она просто скрывает детали распределения для вашей программы.

person TieDad    schedule 24.12.2012

Никогда не используйте gets() (со страницы руководства):

Проверка на переполнение буфера не выполняется.

В зависимости от того, что там введено, происходит переполнение буфера.

person Andreas Florath    schedule 24.12.2012

new char

Выделяет память для ОДНОГО символа. Он может выйти из строя после второго символа (фактически даже после первого, поскольку вы получите символ '\ 0'.

Пожалуйста, используйте C ++, если вы помечаете вопрос как C ++, а не C! Это означает использование std :: string

person Tristram Gräbener    schedule 24.12.2012