Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 06.05.2015, 01:17
crossmark crossmark вне форума
Прохожий
 
Регистрация: 07.09.2009
Сообщения: 7
Репутация: 10
По умолчанию Указатели от теории к практике

Здравствуйте!

Вопрос у меня вот в чем.
Как то не приходилось работать с указателями. Почитав материал вроде все понятно. Получить адрес, разыменовать указатель. Но вот на практике, что-то не то. Или потому что нет самой практики в этой теме.
К примеру вот такая запись:
Код:
type
  TMass = array of byte;
  PMass = ^TMass;
End;
Я так это понял. Объявил тип: TMass массив байтов. Потом объявил PMass который является указателем на Tmass.
Это верно?

Я создаю класс - поток. Стандартный Tthread. TClientReadWriteData = class(TThread)
Код:
type
  TMass = array of byte;
  PMass = ^TMass;
  TClientReadWriteData = class(TThread)
  private
	bf: PMass;  //- объявил буфер котрый является указателем на Tmass
bf_size: integer;
Это верно?

Выделяю память
Код:
constructor TClientReadWriteData.Create;
begin
inherited Create(true);
bf_size:=32768;
//new(bf); // я делал сначала так
//SetLength(bf^, bf_size*sizeof(byte));  // так как это динамический массив. Выделил память
//указателю, потом память под массив

  GetMem(bf, bf_size*sizeof(byte));	// потом сделал так
end;
Мне вот интересна запись в комментарии. Что такое bf. new(bf); Создается переменная указатель. По какому то адресу. Потом SetLength(bf^,….) по этому адресу будет находится адрес массива… Так?
А вот GetMem – сразу выделил память для bf

Далее процедура потока.
Код:
procedure TClientReadWriteData.Execute;
var s: string;
begin
s:= string(pointer(bf));	// проверяю для себя
end;
Вот что заметил. Когда выделял bf через New и SetLength, то переменная s получала значения несколько (примерно около 10) мусорных символов, а вот когда через GetMem то было много мусорных символов.
Код:
procedure TClientReadWriteData.Execute;
var s: string;
begin
//s:= string(pointer(bf));	// проверяю для себя
sz:= recv(_ClientSocket, bf^, bf_size, 0);
s:= string(pointer(bf));
 s:= string(@bf);
end;

Теперь s получает значение которые прочитал сокет. Опять же. Если через New что там не вся строка. А несколько символов. Если Через GetMem – то тут будет вся строка + после нее мусор. (но этот мусор понятен).
Очень интересна строчка s:= string(@bf); тут вся строка – но вначале несколько символов мусора.

Потом идет чтение и запись. Фрагмент кода
Код:
procedure TClientReadWriteData.Execute;
var s: string;
begin
sz:= recv(_ClientSocket, bf^, bf_size, 0);
//код
While true do
Begin
	_size := recv(_ClientSocket, bf^, bf_size, 0);
	//код
send(_ServerSocket, bf^, _size, 0);
End;
end;

В какой то момент в каком то потоке получается не существующий адрес.
Может прокси нормально отработать. Загрузить страницу – одну – две. А может на первой странице вылетит ошибка Access Violation.
Я много раз просматривал и вот что когда для bf выделяется память на номера 118…-120..-130.. все работает, а вот когда на 400… то ошибка.
И что странно выпадает не при первом чтение (до цикла while) а вот уже в самом цикле while.

В чем может быть ошибка? не правильно использую указатели?
Подскажите как правильно должно быть.
Изображения
Тип файла: png error.png (21.7 Кбайт, 3 просмотров)
Ответить с цитированием
  #2  
Старый 06.05.2015, 08:34
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Не пользуйся указателями, они есть зло.
Лучше используй коллекции.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
  #3  
Старый 06.05.2015, 10:14
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

Код:
type
  TMass = array of byte;
  PMass = ^TMass;
Это как раз тот случай, когда ТАК делать не надо. PMass - лишняя сущность.
Если хочется использовать именно указатели, то что-то подобное делается так:
Код:
type
  TMass = array[0 .. MaxInt -4] of byte;
  PMass = ^TMass;

И как раз вот так использовать
Код:
constructor TClientReadWriteData.Create;
begin
  inherited Create(true);
  bf_size:=32768;
 
  GetMem(bf, bf_size*sizeof(byte)); //  так
end;
И так
Код:
s:= string(pointer(bf))


А когда делаете так
Код:
s:= string(@bf);
,то пытаетесь превратить в строку указатель не на данные, а на переменную bf.
Ответить с цитированием
Этот пользователь сказал Спасибо icWasya за это полезное сообщение:
crossmark (06.05.2015)
Ответ


Delphi Sources

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

Расширенный поиск
Опции просмотра

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

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 11:53.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter