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

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

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

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

Цитата:
то в позиции 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 код Выкл.

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

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


11:30.


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

RusProfile.ru


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