Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
 
59 / 48 / 12
Регистрация: 25.01.2010
Сообщений: 248
1

Странное поведение char при выводе в Edit

27.09.2018, 17:08. Просмотров 355. Ответов 14
Метки нет (Все метки)

C++
1
2
3
4
5
6
7
8
9
10
11
void __fastcall TForm1::Edit2Change(TObject *Sender)
{
char s[2];
AnsiString s1;
if(Edit2->Text != "")
  {
     s1 = Edit2->Text;
  }
strcpy(s,s1.c_str());
Edit1->Text = s;
}
При вводе пяти символов в первом поле они отображаются все, хотя при пошаговом просмотре в билдере переменная char имеет два символа. При вводе шести символов выдает ошибку - access violation. Почему так происходит? (C++Builder 10.2)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.09.2018, 17:08
Ответы с готовыми решениями:

Странное поведение при разном объявлении строки char*
Здравствуйте. Я не могу понять в чем проблема. Я описываю глобальную переменную в заголовочном...

Странное поведение ПК при старте
Всем привет!Во время запуска пк,кулера гаснут,изображения нету.Все это длится 1-2 секунды и...

Странное поведение при загрузке
Доброго времени суток! Ситуация такая,Имеется материнка ASUS P8P67 rev. B3 четыре планки памяти...

Странное поведение при делегировании
Доброй ночи, Господа. Пишу некую доп. функциональность к календарю, но дело, собственно, не в...

14
907 / 586 / 290
Регистрация: 22.02.2018
Сообщений: 1,736
Записей в блоге: 2
28.09.2018, 07:26 2
Цитата Сообщение от samsebe Посмотреть сообщение
char s[2];
объявлен массив из 2-х символов, а Вы пытаетесь запихнуть туда больше, ясно дело Access violation при попытке записи по "несуществующему" адресу

Добавлено через 1 минуту
вопрос №2, зачем использовать char, когда есть String/AnsiString?
0
Практикантроп
4621 / 2554 / 479
Регистрация: 23.09.2011
Сообщений: 5,472
28.09.2018, 08:14 3
TrollHammer, "ясное" не до конца "дело". В том-то и дело, что 'исключение' возникает не при попытке внести в массив первый же лишний символ; на "домашней" машине у меня ошибка выскакивала после третьего лишнего, а вот на работе сегодня она вообще не возникает. Я считаю, что это глюк, связанный с реализацией этого самого strcpy , и понять логически причину такого поведения можно только детально разобрав работу соотв. модуля, а это не продуктивно...
0
907 / 586 / 290
Регистрация: 22.02.2018
Сообщений: 1,736
Записей в блоге: 2
28.09.2018, 08:16 4
Цитата Сообщение от nick42 Посмотреть сообщение
Я считаю, что это глюк, связанный с реализацией этого самого strcpy
Согласен, поэтому сам стараюсь избегать использование функций, уходящих корнями в глубокую древность
0
nick42
28.09.2018, 08:21
  #5

Не по теме:

TrollHammer, а я не согласен с тем, что в древности - как вы говорите - писали программы хуже, чем теперь.

0
51 / 39 / 15
Регистрация: 20.09.2018
Сообщений: 163
28.09.2018, 08:44 6
Наверно это зависит от опций компилятора и отладчика.
0
TrollHammer
28.09.2018, 08:51
  #7

Не по теме:

Не совсем понятно, что хотел реализовать ТС в этом обработчике. Изменение текста в Edit1 при изменении Edit2? Если это - то зачем так заморачиваться?

C++
1
2
3
4
void __fastcall TForm1::Edit2Change(TObject *Sender)
{
   Edit1->Text = Edit2->Text;
}

0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
30337 / 19829 / 7750
Регистрация: 22.10.2011
Сообщений: 34,577
Записей в блоге: 6
28.09.2018, 09:18 8
Цитата Сообщение от nick42 Посмотреть сообщение
понять логически причину такого поведения можно только детально разобрав работу соотв. модуля
Ничего тут не надо разбирать. Достаточно знать, что strcpy просто берет начальный адрес источника и приемника, и тупо увеличивает оба их и копирует символ за символом, пока в источнике не встретится 0, при этом перезаписывая те значения, которые были там, куда указывает текущий указатель приемника. Не проверяя никаких границ. Вот в какой-то момент strcpy портит содержимое указателя на строку, например, он начинает указывать "в космос", и при попытке обращения по этому указателю имеем вышеозначенную ошибку.
2
59 / 48 / 12
Регистрация: 25.01.2010
Сообщений: 248
29.09.2018, 03:04  [ТС] 9
Цитата Сообщение от TrollHammer Посмотреть сообщение
ясно дело Access violation при попытке записи по "несуществующему" адресу
Что странно, ошибка возникает вот здесь Edit1->Text = s, а копируется нормально. И отладчик показывает два символа в char.
0
162 / 111 / 59
Регистрация: 12.07.2018
Сообщений: 277
29.09.2018, 09:54 10
Цитата Сообщение от samsebe Посмотреть сообщение
отладчик показывает два символа в char
Объявленный в коде размер s равен 2, поэтому отладчик всегда будет показывать два символа, независимо того, записал strcpy что-то за пределами s или нет.
0
59 / 48 / 12
Регистрация: 25.01.2010
Сообщений: 248
30.09.2018, 03:47  [ТС] 11
Цитата Сообщение от volvo Посмотреть сообщение
strcpy просто берет начальный адрес источника и приемника, и тупо увеличивает оба их и копирует символ за символом, пока в источнике не встретится 0, при этом перезаписывая те значения, которые были там, куда указывает текущий указатель приемника.
Тогда мы сами должны позаботится о нашей переменной char.
C++
1
2
strcpy(s,s1.c_str());
s[sizeof(s)-1] = 0;
Теперь переменная заканчивается правильно и имеет размер указанный ранее. Но и сейчас Edit1->Text = s вызывает ошибку.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
30337 / 19829 / 7750
Регистрация: 22.10.2011
Сообщений: 34,577
Записей в блоге: 6
30.09.2018, 12:02 12
Цитата Сообщение от samsebe Посмотреть сообщение
Теперь переменная заканчивается правильно
И что? В процессе копирования ты все равно портишь несколько байтов, которые не помещаются в s (все, что после 2-го символа строки s1 пишется в область, не принадлежащую s), так что ничего и не изменилось.

Кликните здесь для просмотра всего текста
Ну вот смотри: ты - экскаваторщик. Тебе сказали, что нужно прокопать траншею глубиной 1 метр из точки A. Длина траншеи = 6 метров. Ты начал копать. И, несмотря на то, что через 2 метра у тебя на пути перпендикулярно проложен кабель, ты копаешь дальше, разрушая на фиг этот кабель. Потому что отметка "6 метров" еще не достигнута. Как только ты прокопал все 6 метров - ты выходишь из экскаватора, и с чувством исполненного долга ставишь табличку "Траншея закончилась здесь". А потом удивляешься, а чего это во всем районе нет света (или интернета, смотря какой кабель был). Ты же табличку-то поставил, пофиг что кабель разорван на куски, правда? Раз есть табличка - свет должен быть...


Чтобы исправить ситуацию - надо либо увеличить размер s (в идеале - выделять s динамически), либо заменить strcpy на strncpy, чтобы ограничить количество копируемых символов длиной буфера, и вот тогда уже не забывать добавлять завершающий ноль. Вот в этом случае ничего портиться не будет, тогда можно будет проверять, работает код или нет.
0
59 / 48 / 12
Регистрация: 25.01.2010
Сообщений: 248
30.09.2018, 12:20  [ТС] 13
Цитата Сообщение от volvo Посмотреть сообщение
все, что после 2-го символа строки s1 пишется в область, не принадлежащую s
Размер переменной остается, последний символ '\0', тогда откуда система знает, что что-то было скопировано за пределы переменной?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
30337 / 19829 / 7750
Регистрация: 22.10.2011
Сообщений: 34,577
Записей в блоге: 6
30.09.2018, 12:29 14
В том-то и проблема, что система этого не знает. Знала бы - в тот момент, когда первый байт попытался бы вылезти за пределы буфера - вылетела бы тут же с ошибкой (как это делается в любом нормальном языке, в котором есть проверка выхода за пределы массива). Просто то, что раньше лежало за пределами этого буфера и имело какой-то смысл, указывало куда-то, например, или, еще лучше - это были команды процессору (оно же в стеке все), теперь этого смысла не имеет, теперь там, где должен был быть указатель (и, заметь, где приложение ищет указатель) находятся байты твоей строки. Система интерпретирует их как указатель, и пытается перейти по адресу, который у нее получился. Как ты думаешь, что произойдет?

Я там выше дописал кое-что, почитай.
0
59 / 48 / 12
Регистрация: 25.01.2010
Сообщений: 248
30.09.2018, 12:46  [ТС] 15
Из всего я понял вот что: ошибка возникает при выполнении Edit1->Text = s, значит какие то данные функций для этого действия записаны в памяти после переменной s. Когда записываются символы за пределы переменной, то исчезают данные функции и она не может выполниться. Но если данные функций запишутся, по какой нибудь причине, в другом месте, то ошибки не будет.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.09.2018, 12:46

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Странное поведение при отладке
Здравствуйте. Решил написать небольшую тулзу и столкнулся с проблемой: скомпилированный код...

Странное поведение при буте
помогите разобраться. комп старенький достаточно, при включение питания пишет cmos checksum...

Странное поведение double при сложении
Добрый вечер. Столкнулся с шокирующей для себя новостью. Я не умею считать!!! Есть форма из 2х...

Странное поведение при переопределении operator++
Всем привет! Изучая переопределения в С++ наткнулся на следующую непонятку: #include <iostream>...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.