Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.09.23;
Скачать: [xml.tar.bz2];

Вниз

var-Параметры_процедур - указатели. То ли лыжи не едут, ....   Найти похожие ветки 

 
Cobalt ©   (2007-08-29 16:31) [0]

Подскажите, как указать, что процедуре можно передать любой указатель, а то если указать просто Pointer, то она требует обязательно привести к Pointer

procedure ReFillPointer(var p: pointer; len: Cardinal; b: Byte=0);
----
 PSecurityDescriptor = ^TSecurityDescriptor;
var
Desc: PSecurityDescriptor;

----
так - ругается
ReFillPointer(@Desc,len,0);
Types of actual and formal var parameters must be identical

а так - нет:
ReFillPointer(Pointer(Desc),len,0);

Но чёт у меня сомнения насчёт второго варианта...

P.S.
А поставил procedure ReFillPointer(var p: PSecurityDescriptor; len: Cardinal; b: Byte=0); - и не требуется приведение.

Как бы вообще обойтись без приведения?

ей даже {$T-} пофиг...

Чё-то нифига не пойму :(


 
DVM ©   (2007-08-29 16:34) [1]


> А поставил procedure ReFillPointer(var p: PSecurityDescriptor;
>  len: Cardinal; b: Byte=0); - и не требуется приведение.
>

А почему бы так и не оставить? На кой ляд тебе создавать самому себе сложности и потом их героически преодолевать?


 
Cobalt ©   (2007-08-29 16:46) [2]

> DVM ©   (29.08.07 16:34) [1]
хочется иметь универсальную процедуру, а не писать на каждый acl, sid и прочие закрытые указатели по процедуре, или же оборачивать их в pointer.


 
DVM ©   (2007-08-29 16:51) [3]


> хочется иметь универсальную процедуру,

Источник потенциальных ошибок. Строгая типизация она ведь больше пользы приносит.


 
Сергей М. ©   (2007-08-29 16:53) [4]


> как указать, что процедуре можно передать любой указатель


const Param
var Param
out Param

Выбирай на вкус.


 
Юрий Зотов ©   (2007-08-29 17:01) [5]

> Cobalt ©   (29.08.07 16:31)  

procedure ReFillPointer(var p: pointer; len: Cardinal; b: Byte=0);

type
 PSecurityDescriptor = ^TSecurityDescriptor;
var
 Desc: PSecurityDescriptor;
----
 ReFillPointer(@Desc, len, 0);

Передается не указатель, а его адрес. Вряд ли Вы хотели именно этого. Кроме того, параметр объявлен с описателем var, поэтому передача результата операции @ вместо явной переменной здесь не прокатит.

А вот так все должно прокатывать:
ReFillPointer(Desc, len, 0);
поскольку в парамерах процедуры стоит просто pointer. То есть, ЛЮБОЙ указатель.


 
Cobalt ©   (2007-08-29 17:25) [6]

> Юрий Зотов ©   (29.08.07 17:01) [5]
> Передается не указатель, а его адрес. Вряд ли Вы хотели именно этого.


именно этого-то и хотел. Вот полностью код, который проясняет необходимость передачи указателя по ссылке.

procedure ReFillPointer(var p: PSecurityDescriptor; len: Cardinal; b: Byte=0);
begin
  if p<>nil
  then begin
         FreeMem(p);
       end;
  GetMem(p, len);
  FillChar(p^, len, b);
end;


Читаю справку, и не могу понять, чтоже я делаю не так:

If a routine"s declaration specifies a var parameter, you must pass an assignable expression--that is, a variable, typed constant (in the {$J+} state), dereferenced pointer, field, or indexed variable


 
Cobalt ©   (2007-08-29 17:28) [7]

Собственно вопрос в том, как убрать явное преобразование к нетипизированному указателю (pointer) при вызове этой функции если ее объявить как procedure ReFillPointer(var p: Pointer; len: Cardinal; b: Byte=0);


 
DVM ©   (2007-08-29 17:33) [8]


> Cobalt ©   (29.08.07 17:25) [6]


> FreeMem(p);

Утечек не получится? Если указатель будет нетипизированным.


 
umbra ©   (2007-08-29 17:35) [9]


> FreeMem(p);

у FreeMem может быть 2 параметра. Второй - размер области памяти, на которую указывает первый параметр. Если передавать первым нетипизированный указатель, то как функция узнает, сколько памяти освобождать?


 
Cobalt ©   (2007-08-29 19:06) [10]

Так второй же параметр необязателен, вы чё?
Менеджер памяти сам знает, сколько у него по этому адресу выделено памяти.


 
Cobalt ©   (2007-08-29 19:31) [11]

Собственно вопрос - откуда несовместимость???
Почему конкретный указательный тип несовместим с Pointer в параметре процедуры?


 
Инс ©   (2007-08-29 19:59) [12]


> [9] umbra ©   (29.08.07 17:35)


Cobalt прав. Второй параметр у FreeMem оставлен только для совместимости со старым кодом и на самом деле не используется. Размер памяти, который нужно освободить, менеджер всегда определяет опираясь на свои записи.

Скорее всего Вы путаете с процедурой Dispose, которой действительно нужно передавать типизированный указатель, иначе память будет освобождена некорректно.


 
DVM ©   (2007-08-29 20:11) [13]


> Cobalt прав. Второй параметр у FreeMem оставлен только для
> совместимости со старым кодом и на самом деле не используется.
>

Если в процедуру передается нетипизированный указатель на вот такую запись и потом внутри процедуры происходит FreeMem, то имхо компилятор не может построить внутри процедуры код, который корректно освободит память под строки.

type
 TMyRec = record
    s1: string;
    s2: string;
 end;
 PMyRec = ^TMyRec;


 
Инс ©   (2007-08-29 20:23) [14]


> именно этого-то и хотел


Вы хотели передать адрес указателя??? Вот смотрите, у вас есть указатель, значение которого $XXXXXXXX. Сама переменная указательного типа находится по адресу $YYYYYYYY скажем, в стеке, если это локальная переменная. Так вот, вызовом
ReFillPointer(@Desc,len,0);
вы пытаетесь передать в процедуру именно $YYYYYYYY, а вам скорее всего нужно $XXXXXXXX. Еще раз перечитайте [5].


> А поставил procedure ReFillPointer(var p: PSecurityDescriptor; len: Cardinal; b: > Byte=0); - и не требуется приведение.

Уверен, что если "собаку" в вызове оставили, то не работает, компилятор не пропустит. Так как var-параметр должен быть именно переменной, а не значением (адрес переменной - это значение). var уберете - и с "собакой" компилятор пропустит.


 
Инс ©   (2007-08-29 20:27) [15]


> Если в процедуру передается нетипизированный указатель на
> вот такую запись и потом внутри процедуры происходит FreeMem,
> то имхо компилятор не может построить внутри процедуры код,
> который корректно освободит память под строки.

Естественно. FreeMem - это "тупое" освобождение памяти. FreeMem не умеет работать со сложными структурами данных, содержащих длинные строки, динмассивы и пр. Для таких записей нужно выделять память с помощью New, а освобождать - Dispose. New не только выделяет память под структуру, но и инициализирует поля сложных типов. А Dispose финализирует их и освобождает память.


 
Инс ©   (2007-08-29 20:30) [16]

Кстати, не имеет значения, типизированный или нетипизированный указатель передается в FreeMem. Он все равно освобождает память "тупо".


 
DVM ©   (2007-08-29 20:35) [17]


> А Dispose финализирует их и освобождает память.

Если Dispose() передать нетипизированный указатель на структуру из [13], то тоже будет утечка скорее всего.


 
Инс ©   (2007-08-29 20:35) [18]


> Собственно вопрос - откуда несовместимость???

Из-за ключевого слова var. Тип актуального и формального параметра должны быть идентичны, об этом вам сообщение об ошибке и утверждает. C Integer и Cardinal тоже не прокатит, не только в Pointer-ах проблема.


 
Инс ©   (2007-08-29 20:37) [19]


> [17] DVM ©   (29.08.07 20:35)

Не скорее всего, а точно. Я же написал в [12], что Dispose нужно передавать типизированный указатель. А FreeMem - по барабану. Вы с каким утверждением спорите? :) Что непонятно? Могу попытаться разъяснить


 
DVM ©   (2007-08-29 20:41) [20]


> Вы с каким утверждением спорите? :) Что непонятно?

Я не спорю. Все верно. Не заметил слово "типизированный".


 
Инс ©   (2007-08-29 20:44) [21]


> [20] DVM ©   (29.08.07 20:41)


Вы тоже видимо в [8] с Dispose перепутали...


 
wp2 ©   (2007-08-30 13:30) [22]

мдя... а я всегда думал, что указатель и адрес это одно и тоже :-)

Правда никогда бы этого не утверждал.


 
Инс ©   (2007-08-30 13:40) [23]


> мдя... а я всегда думал, что указатель и адрес это одно
> и тоже :-)

Неправильно предполагали. Адрес - это значение, по которому в памяти располагаются те или иные данные. Указатель - это тип данных, содержащий в себе адрес. В данном случае @Desc - это адрес переменной указательного типа, т.е. адрес переменной содержащей другой адрес. Сложно? Разберитесь.


 
KSergey ©   (2007-08-30 13:42) [24]

По исходному вопросу.
Это лыжи не едут, однозначно :) ЮЗ все же объяснил уже.

В var параметр можно передавать только переменную и ничего более.
Приведенный пример - тоже самое, что нельзя делать, например, так:

procedure MyProc(var i: Integer);
beain
...
end;
.....

var
  L: Integer;
...
MyProc(L + 5);


Однако можно так:

var
  L: Integer;
...
L := L + 5;
MyProc(L);


Ферштейн?


 
KSergey ©   (2007-08-30 13:44) [25]

В дополнение к > KSergey ©   (30.08.07 13:42) [24]

хотя в MyProc(L + 5) передаваемый параметр - типа Integer.

Ошибка будет, наверное, другая при компиляции этого примера, но смысл - по-моему как раз.


 
Инс ©   (2007-08-30 13:45) [26]


> ЮЗ все же объяснил уже.

ЮЗ объяснил не совсем все. В частности вот это:

> А вот так все должно прокатывать:
> ReFillPointer(Desc, len, 0);

не верно.


 
Anatoly Podgoretsky ©   (2007-08-30 13:51) [27]

> KSergey  (30.08.2007 13:44:25)  [25]

Но не переменная и поэтому значение некуда присваивать



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.09.23;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.073 c
15-1188182876
Slider007
2007-08-27 06:47
2007.09.23
С днем рождения ! 27 августа 2007 понедельник


15-1187856224
Alien1769
2007-08-23 12:03
2007.09.23
Пособие для руководителей


2-1188472359
kudatsky
2007-08-30 15:12
2007.09.23
Можно-ли ввести данные в TStringGrid в Design Time ?


15-1188287010
infom
2007-08-28 11:43
2007.09.23
Не могу использовать на форме TWebBrowser в BDS 2006 !


15-1187882160
Joan
2007-08-23 19:16
2007.09.23
SQL





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский