Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RusFAQ.ru: Программирование на C / C++


РАССЫЛКИ ПОРТАЛА RUSFAQ.RU

/ КОМПЬЮТЕРЫ И ПО / Языки программирования / C/C++

Выпуск № 860
от 27.09.2007, 17:05

Администратор:Калашников О.А.
В рассылке:Подписчиков: 479, Экспертов: 61
В номере:Вопросов: 2, Ответов: 5


Вопрос № 102964: Уважаемые эксперты, помогите разобраться. Сижу в среде Borland C++ Builder 6. На форме имеется окно TEdit. Ввожу в него число. Как сделать, чтобы это число было присвоено некоей переменной при нажатии клавиши Enter? Дмитрий....
Вопрос № 102967: Здравствуйте ув. эксперты Мне в руки попал пример, отлично демонстрирующий как НЕ надо писать) Стало интересно почему в VC++ 6.0 он нормально(по мысли автора) работает, а в builder 6 программа падает на последнем цикле?...

Вопрос № 102.964
Уважаемые эксперты, помогите разобраться. Сижу в среде Borland C++ Builder 6. На форме имеется окно TEdit. Ввожу в него число. Как сделать, чтобы это число было присвоено некоей переменной при нажатии клавиши Enter? Дмитрий.
Отправлен: 22.09.2007, 07:59
Вопрос задал: Горячев Дмитрий (статус: Посетитель)
Всего ответов: 2
Мини-форум вопроса >>> (сообщений: 2)

Отвечает: Виктор Пырлик
Здравствуйте, Горячев Дмитрий!

Используйте событие OnKeyDown компонента TEdit. В этом событии проверяйте введенный код символа (клавиши), определенных в Windows.h - Virtual key codes. Просто, нажмите F1 в инспекторе объектов на вкладке Events.

Приложение:

---------
Если ничего не помогло - надо читать инструкцию

Ответ отправил: Виктор Пырлик (статус: Студент)
Ответ отправлен: 22.09.2007, 10:47
Оценка за ответ: 5
Комментарий оценки:
Спасибо за развернутый ответ и очень подробные дополнительные пояснения. Дмитрий.

Отвечает: Лукьянчиков Дмитрий Сергеевич
Здравствуйте, Горячев Дмитрий!

Создайте строковую переменную и присвойте ей strtoint(TEdit).


---------
Программирование - вещь полезная!
Ответ отправил: Лукьянчиков Дмитрий Сергеевич (статус: 1-ый класс)
Ответ отправлен: 24.09.2007, 19:47
Оценка за ответ: 3
Комментарий оценки:
Ответ сколь лаконичен, столь же и непонятен. Дмитрий.


Вопрос № 102.967
Здравствуйте ув. эксперты
Мне в руки попал пример, отлично демонстрирующий как НЕ надо писать)
Стало интересно почему в VC++ 6.0 он нормально(по мысли автора) работает, а в builder 6 программа падает на последнем цикле?

Приложение:

Отправлен: 22.09.2007, 08:27
Вопрос задал: Sov (статус: 7-ой класс)
Всего ответов: 3
Мини-форум вопроса >>> (сообщений: 0)

Отвечает: Maxim V.G.
Здравствуйте, Sov!
Ответом на этот вопрос будет оптимизация работы с памятью компилятора BCB 6. Вероятнее всего программа падает из-за того что на последнем цикле программа обращается к несуществующему (недоступному) на тот момент участку памяти.
Операции temp = array; и array = temp; копируют указатель на область памяти где храняться данные, а сами данные остаются в одной и тойже области. Как выход из этой ситуаци я могу предложить организовать копирование данных во временную переменную и обратно.
Модернизированный код находиться в приложении который должен исправить проблемму.

P.$. Надо не забывать освобождать место выделенное опертором new оператором delete. В противном случае можно получить переполнение памяти!

Приложение:

---------
Жить вредно - от неё умирают

Ответ отправил: Maxim V.G. (статус: 4-ый класс)
Ответ отправлен: 22.09.2007, 13:28
Оценка за ответ: 4
Комментарий оценки:
Я спросил почему некорректно написанная программа работает, если использовать один компиллятор и падает, если другой. Не нужно ее исправлять и указывать на ошибки.
"оптимизация работы с памятью компилятора BCB 6" подробнее можно?

Отвечает: Rockie
Здравствуйте, Sov!

Хотел отослать ответ а потом взглянул на ваш комментарий. В любом случае отвечу, включив первый вариант ответа.

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

Давайте взглянем на код, некоторые строки я отбросил, но порядок не менял.

// здесь автор выделил память под указатель array
int* array = new int[size];

// здесь автор выделил память под указатель temp
temp = new int[size];

// а здесь утечка памяти, указателю temp присвоен другой адрес и уже нельзя добраться до памяти,
// выделенной под указатель temp
temp = array;

// Это неправильно, выше автор выделил память под указатель array, а теперь выделил еще раз.
// new вернула в array новый адрес и указатель на ранее выделенную под array память потерян.
// Теперь до нее нельзя добраться, хотя этот ранее выделенный участок продолжает находится в памяти.
array = new int[size];

// И т.д.
Даже если автор и "сохранил" адрес array в указателе temp, он уже не сможет корректно вызвать delete для ранее выделенного под array участка памяти.
--------------

А теперь уже по вашему вопросу.

Если быть точным, то у меня в BCB 6 эта программа вообще не компилируется: [C++ Error] Unit1.cpp(45): E2292 Function should return a value).
В C++ main() по стандарту должен возвращать int. Хотя современные компиляторы обычно добавляют возврат инта автоматически, это не значит что так будет происходить в 100% случаев.

Если изменить код на

return 0;

то программа действительно будет падать, только не на последнем, а на предпоследнем цикле, по причине access violation:

array = temp; // настроили указатель на участок памяти в 5 int-ов
for (i = 5; i < size; i++) // выходим за предел массива
{
array[i] = i;
}

Вы спрашиваете:
"Я спросил почему некорректно написанная программа работает, если использовать один компиллятор и падает, если другой."

Это зависит от того, как собирается проект(debug/release), от менеджера памяти, от того, используется ли память, которую вы заняли, другими процессами.

Также на мой взгляд не совсем точная формулировка - "работает". Эта программа содержит ошибку выхода за предел массива. Возможно при сборке под VC 6, если память не занята другими процессами, ничего и не будет. Но это не значит, что программа работает, так как ничто не гарантирует, что в один прекрасный день она не грохнет какой-нибудь (например системный) процесс.


Ответ отправил: Rockie (статус: 4-ый класс)
Ответ отправлен: 22.09.2007, 18:04
Оценка за ответ: 4
Комментарий оценки:
return-пардон опечатка вышла, забыл нолик дописать
"зависит от того, как собирается проект"-как зависит(примеры, статьи, ссылки)?
И при чем тут другие процессы(в том числе и системные)? Программа выполняется в своем адресном пространстве и никого "не трогает"
Формулировка значения не имеет. Поняно что под словом "работает" я подразумевал то что программа не падает с исключением.

Отвечает: Алексей Демаков
Здравствуйте, Sov!

Судя по оценкам предыдущих ответов, ясность в поставленном вопросе не достигнута. Попробую ответить. Очевидно, что проблема в том, как программа работает с памятью.
Нельзя гарантировать, что запись в цикле после присваивания array = temp происходит в память, которая ранее выделена оператором new. При такой записи может случиться все, что угодно:
1. Программа модифицирует доступную на запись память, которая не принадлежит ни одной из ее переменных. Это действие не приведет к падению. Записанные данные можно прочитать, храниться они будут до тех пор, пока эта память не будет выделена и перезаписана. После этого данными мистическим образом изменятся :)
2. Программа модифицирует доступную на запись память, которая принадлежит ни одной из ее переменных. Значение этой переменной мистическим образом изменится, поведение программы скорее всего окажется странным. Может быть, программа упадет.
3. Программа модифицирует недоступную на запись память. Тут же возникнет исключительная ситуация - нарушение режима доступа к памяти.

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

Если блоки памяти выделяются друг за другом по возрастанию адресов, то программа будет работать корректно - элементы массива с индексами от 0 до 4 будут размещены в первом выделенном блоке, от 5 до 9 - во втором. Третий блок (размера 10) не будет использоваться вовсе.

Если блоки выделяются начиная с максимального адреса, выше которого память на запись не доступна, то элементы массива с индексами от 0 до 4, как и в предыдущем случае, будут размещены в первом выделенном блоке, а вот элементы с индексами от 5 до 9 разместятся в памяти, доступ на запись в которую закрыт. Второй и третий блоки памяти будут иметь меньшие адреса, чем первый.

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

Все вышесказанное - это гипотеза. Реальной стратегии распределения памяти этих компиляторов я не знаю. Проверить адреса выделенных блоков памяти можно с помощью дополнительной отладочной печати.
Ответ отправил: Алексей Демаков (статус: Студент)
Ответ отправлен: 22.09.2007, 23:52
Оценка за ответ: 5
Комментарий оценки:
Правдоподобная гипотеза)


Отправить вопрос экспертам этой рассылки

Приложение (если необходимо):

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

Обратите внимание!
Вопрос будет отправлен всем экспертам данной рассылки!

Для того, чтобы отправить вопрос выбранным экспертам этой рассылки или
экспертам другой рассылки портала RusFAQ.ru, зайдите непосредственно на RusFAQ.ru.


Форма НЕ работает в почтовых программах The BAT! и MS Outlook (кроме версии 2003+)!
Чтобы отправить вопрос, откройте это письмо в браузере или зайдите на сайт RusFAQ.ru.


© 2001-2007, Портал RusFAQ.ru, Россия, Москва.
Авторское право: ООО "Мастер-Эксперт Про"
Техподдержка портала, тел.: +7 (926) 535-23-31
Хостинг: "Московский хостер"
Поддержка: "Московский дизайнер"
Авторские права | Реклама на портале
Версия системы: 4.60.05 от 27.09.2007
Яндекс Rambler's Top100
RusFAQ.ru | MosHoster.ru | MosDesigner.ru | RusIRC.ru
Kalashnikoff.ru | RadioLeader.ru | RusFUCK.ru

В избранное