Текущий архив: 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.52 MB
Время: 0.046 c