Форум программистов
 
Расширенный поиск
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > Delphi > Lazarus, Free Pascal, CodeTyphon
Регистрация

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



Ответ
 
Опции темы
Старый 17.11.2017, 22:12   #1
Alexan-Dwer
Форумчанин
 
Аватар для Alexan-Dwer
 
Регистрация: 20.04.2009
Адрес: Россия
Сообщений: 136
Репутация: 38
Вопрос Решено: Массив символов и указатели

Сделал процедуру для обновления ScrollBar у ComboBox:

Код:

procedure MaxWidthComboBoxScroll(Handle: HWND);
var
//
ws: lpSize;
//
HandleDC: HDC;
//
CurrentStrChars: array of Char;
//
i, k, MaxWidth, CurrentWidth, CurrentStrLn: Cardinal;
begin
//
MaxWidth:=0;
//
GetMem(ws, SizeOf(lpSize));
//
HandleDC:=GetDC(Handle);
//
k:=SendMessage(Handle, CB_GETCOUNT, 0, 0) - 1;

//
for i:=0 to k do
  begin
  //
  CurrentStrLn:=SendMessage(Handle, CB_GETLBTEXTLEN, i, 0);
  //
  SetLength(CurrentStrChars, CurrentStrLn);
  //
  SendMessage(Handle, CB_GETLBTEXT, i, lParam(@CurrentStrChars[0]));
  //
  GetTextExtentPoint32(HandleDC, @CurrentStrChars[0], CurrentStrLn, ws^);
  //
  CurrentWidth:=ws^.cx;
  //
  if MaxWidth < CurrentWidth then MaxWidth:=CurrentWidth;
  end;

//
SendMessage(Handle, CB_SETHORIZONTALEXTENT, MaxWidth + 5, 0);
//
FreeMem(ws, SizeOf(lpSize));
//
ws:=nil;
end;

Работает, но в другом месте появляется ошибка: SIGSEGV. Нашел, что ее причина эта процедура, а именно, массив символов. Если его сделать не динамическим (убрать CurrentStrLn:=SendMessage(Handle, CB_GETLBTEXTLEN, i, 0); SetLength(CurrentStrChars, CurrentStrLn);), а объявить так:
Код:

CurrentStrChars: array [0..255] of Char;

То все нормально. Так же, ошибка не возникает если заменить массив символов CurrentStrChars на строку CurrentStr, и вместо @CurrentStrChars[0] указать @CurrentStr[1].

И последнее, самое интересное: если дополнительно увеличить длину массива символов на один, то есть:
Код:

SetLength(CurrentStrChars, CurrentStrLn + 1);

И это меня удивило!

По спецификации, это нужно вроде только для CB_GETLBTEXT:
Цитата:
A pointer to the buffer that receives the string. The buffer must have sufficient space for the string and a terminating null character.
Однако, если просмотреть через отладчик, то даже если длина установлена как CurrentStrLn, без "+ 1", то в позиции CurrentStrLn массива CurrentStrChars значение #0. То есть, CB_GETLBTEXT передает символ завершения строки без ошибки. Так же, как и если присваивать по этому индексу любое значение вручную.

Что же тогда происходит?

Последний раз редактировалось Alexan-Dwer; 17.11.2017 в 23:08. Причина: Найдено решение
Alexan-Dwer вне форума   Ответить с цитированием
Старый 17.11.2017, 22:41   #2
evg_m
Профессионал
 
Регистрация: 20.04.2008
Сообщений: 4,503
Репутация: 2041
По умолчанию

Цитата:
то в позиции CurrentStrLn массива CurrentStrChars значение #0.
эта позиция НЕ принадлежит указанному массиву
Цитата:
То есть, CB_GETLBTEXT передает символ завершения строки без ошибки
но принадлежит какому-то ДРУГОМУ объекту(массиву, строке, ...) программы и потому доступен для изменения.
А вот когда мы захотим
Цитата:
но в другом месте
использовать ЭТОТ другой объект его значение будет неверное и более того может завести нас куда угодно(заставить обратиться к недоступной(запрещенной) памяти), что и приведет к
Цитата:
но в другом месте появляется ошибка: SIGSEGV.
мы некорректно изменили что-то другое и это привело к ошибке.
__________________
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 17.11.2017 в 22:43.
evg_m вне форума   Ответить с цитированием
Старый 17.11.2017, 22:51   #3
Alexan-Dwer
Форумчанин
 
Аватар для Alexan-Dwer
 
Регистрация: 20.04.2009
Адрес: Россия
Сообщений: 136
Репутация: 38
По умолчанию

evg_m, спасибо, действительно, видимо Вы правы

В таком случае, как вариант, можно так:
Код:

...
//
T: Char;
...
//
T:=CurrentStrChars[CurrentStrLn];
...
//
CurrentStrChars[CurrentStrLn]:=T;

восстановить работоспособность?

Логичнее, конечно, просто добавить длину, но для истинности проверю и такой способ.

P. S. Да, evg_m абсолютно прав, восстановив значение, ошибка не возникает. Спасибо за исправление моей невнимательности.

Последний раз редактировалось Alexan-Dwer; 17.11.2017 в 23:05.
Alexan-Dwer вне форума   Ответить с цитированием
Ответ



Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[СИ, Указатели]: Ввести строку их трёх символов и вывести первые два. CortesGames Помощь студентам 10 17.12.2016 01:17
Си.Массив.Указатели BERTY123 Помощь студентам 0 23.12.2015 17:27
Указатели на массивы символов Pillowo47 Общие вопросы C/C++ 14 05.07.2013 10:16
Как конвертировать массив символов в массив байт davinci C++ Builder 6 30.10.2010 18:09
массив и указатели SkrudjMakdak Общие вопросы Delphi 11 25.09.2010 13:07




08:33.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

купить трафик


как улучшить посещаемость, а также решения по монетизации сайтов, видео и приложений

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru