Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

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

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

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.11.2017, 21:12   #1
Alexan-Dwer
Форумчанин
 
Аватар для Alexan-Dwer
 
Регистрация: 20.04.2009
Сообщений: 136
Вопрос [РЕШЕНО] Массив символов и указатели

Сделал процедуру для обновления 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 передает символ завершения строки без ошибки. Так же, как и если присваивать по этому индексу любое значение вручную.

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

Решение: http://www.programmersforum.ru/showp...21&postcount=2

Последний раз редактировалось Вадим Мошев; 07.05.2018 в 18:43. Причина: Найдено решение
Alexan-Dwer вне форума Ответить с цитированием
Старый 17.11.2017, 21:41   #2
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,515
По умолчанию

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

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

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

В таком случае, как вариант, можно так:
Код:
...
//
T: Char;
...
//
T:=CurrentStrChars[CurrentStrLn];
...
//
CurrentStrChars[CurrentStrLn]:=T;
восстановить работоспособность?

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

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

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


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[РЕШЕНО] С# Строка как массив YbeysaOBSenky C# (си шарп) 2 14.11.2017 16:35
[СИ, Указатели]: Ввести строку их трёх символов и вывести первые два. CortesGames Помощь студентам 10 17.12.2016 00:17
[РЕШЕНО]: Задача. Дан массив размером от 1 до N. sr193 Паскаль, Turbo Pascal, PascalABC.NET 2 12.06.2016 18:09
Указатели на массивы символов Pillowo47 Общие вопросы C/C++ 14 05.07.2013 10:16
массив и указатели SkrudjMakdak Общие вопросы Delphi 11 25.09.2010 13:07