Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.09.23;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.026 c
1-1184221625
alegad
2007-07-12 10:27
2007.09.23
Графика в дельфи


2-1188277836
MultIfleX
2007-08-28 09:10
2007.09.23
Ini


10-1136960796
pavel_guzhanov
2006-01-11 09:26
2007.09.23
Как в Excel открыть файл, находящийся в директории


3-1179408936
Mysql
2007-05-17 17:35
2007.09.23
любая последовательность кавычек и символов в добавляемом тексте


11-1171710316
homm
2007-02-17 14:05
2007.09.23
Форт-подобная машина Владимира Кладова