Форум программистов, компьютерный форум CyberForum.ru

EAccessViolation, если длина строки больше 14 - C++

Восстановить пароль Регистрация
 
VV_RIP
9 / 8 / 1
Регистрация: 05.02.2012
Сообщений: 105
21.02.2013, 20:30     EAccessViolation, если длина строки больше 14 #1
Здравствуйте! Сперва простой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void cyr_print(const char* text)
{
    const int n = strlen(text);
    char *buf = new char[n];
    CharToOem(text, buf);
    cout<<buf<<endl;
    delete buf;
}
//---------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
    char *arr1 = new char[0];
    char *arr2 = new char[0];
    cyr_print("Введите первую строку: ");
    cin>> arr1;
    cyr_print("Введите вторую строку: ");
    cin>> arr2;
    delete arr1;
    delete arr2;
 
    system("pause");
    return 0;
}
Если вводить в консоли до 15 символов в каждый массив, то все работает, если 15 и больше, то ошибка.
Мне интересно, почему именно 15? при этом мы можем на самом деле ввести хоть 30, и все будет норм, программа вылетит только после строчки

C++
1
return 0;
Как так?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.02.2013, 20:30     EAccessViolation, если длина строки больше 14
Посмотрите здесь:

Программа должна определить длину введенной строки L и, если длина L >15, то удаляются все a..z. C++
C++ Ввести строку символов, если ее длина нечетная, удалить символ, стоящий посередине строки.
Если длина строки меньше заданной, то повторить ввод C++
C++ Переменной R присвоить значение 1, если длина вектора А больше длины вектора В, и значение 0 в противном случае
C++ Определить длину введенной строки L, и если длина L четная, то удаляются 3 первых, иначе 3 последних символа
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
21.02.2013, 21:23     EAccessViolation, если длина строки больше 14 #2
Потому что вот что говорит стандарт: 3.7.3.1/2
The allocation function attempts to allocate the requested amount of storage. If it is successful, it shall
return the address of the start of a block of storage whose length in bytes shall be at least as large as the
requested size
.
Поэтому ниже есть еще такое
Even if the size of the space requested is zero, the request can fail.
То есть даже на 0 может не хватить места, например.

Ну и еще
The effect of dereferencing a pointer returned as a request for zero size is undefined
В твоем случае, скорее всего, система отдала 16 байт (15 символов + '\0' строки)
VV_RIP
9 / 8 / 1
Регистрация: 05.02.2012
Сообщений: 105
21.02.2013, 23:21  [ТС]     EAccessViolation, если длина строки больше 14 #3
Хм ... а почему система несмотря на выделение только 16 байт, все равно может записать туда больше? Т.е. получается, что записать она может, но возникают проблемы при закрытии программы при освобождении памяти? Т.е. с одной стороны функция strlen(), например, видит реальный размер, но при закрытии все равно что-то недоудаляется? где-то утечка?
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
21.02.2013, 23:30     EAccessViolation, если длина строки больше 14 #4
а кто ей помешает? Ты же не можешь знать из какой кучи она достала эту память. Если ты под окнами, то система берет из кучи процесса (HeapAlloc(GetProcessHeap(), ...)), например; Обычно эта куча не ограничивается десятками байт. При выходе и проверке обнаруживается нарушение, о чем тебе и сообщается.

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

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

Кстати, отвлеченно от памяти, у тебя еще одна неприятность есть в коде
C++
1
2
3
4
5
    char *arr1 = new char[0];
    char *arr2 = new char[0];
....
    delete arr1;
    delete arr2;
Если ты используешь new [], то должен использовать delete [] для удаления.
VV_RIP
9 / 8 / 1
Регистрация: 05.02.2012
Сообщений: 105
23.02.2013, 23:46  [ТС]     EAccessViolation, если длина строки больше 14 #5
Ах да ... позабыл поставить квадратные скобки)
Да, это под Win, c++ builder.
Причем я заметил такую особенность, что, когда мы только создали переменную, там лежит только один символ '\0', а как только добавляем хоть один элемент, массив автоматом расширяется до 16, включая символ конца строки, конечно.
Проблема (т.е EAccessViolation) исчезает, только если мы ручками определяем размер массива.
Но тут вопрос: зачем тогда выделяется эта память, если при таком её использовании все заканчивается ошибкой?
Причем, если мы выделили память для 7 элементов и используем strlen, то он покажет 7, хотя на самом деле там ведь 16! И мы можем посмотреть содержимое этих 16 элементов. Видимо в памяти хранится ещё кучка дополнительной инфы, какие элементы массива доступны, а какие как бы и есть, но и их и использовать нельзя ... даже можно, но будет ошибка потом. Но на вопрос зачем это не отвечает ...
Yandex
Объявления
23.02.2013, 23:46     EAccessViolation, если длина строки больше 14
Ответ Создать тему
Опции темы

Текущее время: 07:05. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru