-
В Delphi есть замечательное предупреждение: W1035 Return value of function '%s' might be undefined
Если у функции стандартный возвращаемый тип
function GetXxx(...): Integer;
begin
end;
то указанное предупреждение работает отлично.
Однако если возвращается record
type TMyRec = ..... end;
function GetXxx(...): TMyRec;
begin
end;
то указанное предупреждение внезапно перестаёт выдаваться компилятором!!
Вопроса у меня два
1) WTF?!
2) Как бы сделать так, чтобы указанное предупреждение выдавалось не зависимо от возвращаемого типа?
Заранее спасибо.
-
в первом случае скаляр и ругается на значение этого скаляра, которое может быть андефайнед
во втором случае не скаляр и что мы будем понимать под его значением, подразумевая возможную неопределенность?
резалт уже создан, память под него распределена.
ps кстати функция эта плохая.
-
в рекорде сто строковых членов и триста ссылок на TObject
мной проинициализировано 99 строковых членов и 299 ссылок
299-я ссылка ведет в никуда. не в нил, а в недоступную память.
ты - компилятор.
в этом случае будешь предупреждать?
как и зачем?
-
> то указанное предупреждение внезапно перестаёт выдаваться
> компилятором!!
Ты посмотри, что вернется, а потом ругайся на компилятор.
-
Формально такая запись означает
procedure GetXxx(out Result: TMyRec; .....)
Т.е. нет никакого возвращаемого результата, есть некий указатель, а что под ним лежит - ни разу не дело компилятора.
-
> Ты посмотри, что вернется, а потом ругайся на компилятор.
- останется предыдущее значение, которое в большинстве случаев - стековый мусор.
В том числе веселый артефакт - для управляемых типов - при повторном вызове в той же области видимости:
function lime(s: string): string;
begin
if( s <> '' )then
Result:= s;
end;
const ss:array[0..1]of string = ('1', '');
var i;
begin
i:= 0;
if( lime('') = '' )then
while( lime(ss[i]) <> '' )do inc(i);
end;
Поэтому полезно поддерживать портирование на FPC - там анализатор местами более параноидальный...
> 1) WTF?!
- в том числе FPC матерится на не инициализированный
var параметр, семантика которого здесь и имеет место быть.
procedure GetXxx(var : TMyRec);
-
блин - тэг
внутри выглядит оригинально...
...
function lime(s: string): string;
begin
if( s <> '' )then
Result:= s;
end;
const ss:array[0..1]of string = ('1', '');
var i;
begin
i:= 0;
if( lime('') = '' )then
while( lime(ss[i]) <> '' )do inc(i);
end;
...
procedure GetXxx(var Result: TMyRec);
-
блин(рекурсия): '&'+'gt' + ';'+'CODE'+'&'+'gt' + ';' - тоже выглядит неплохо
особенно когда он внутри тэга '&'+'gt' + ';'+'DELPHI'+'&'+'gt' + ';'
...
function lime(s: string): string;
begin
if( s <> '' )then
Result:= s;
end;
const ss: array[0..1]of string = ('1', '');
var i: integer;
begin
i:= 0;
if( lime('') = '' )then
while( lime(ss[i]) <> '' )do inc(i);
end;
...
procedure GetXxx(var Result: TMyRec);
(експеримент: а если так : (&+amp+;) >> )
-
han_malign © (16.03.18 12:01) [5]
> - останется предыдущее значение
Ну так оно же не undefined, верно ? Оно вполне себе defined - то, что было перед вызовом
-
GetXxx(...).SomeMember := 'bla bla bla';
ShowMessage(GetXxx(...).SomeMember);
формально все законно.
таких функций не должно быть на нашей планете
-
> Игорь Шевченко © (16.03.18 12:43) [8]
> > - останется предыдущее значение
> Ну так оно же не undefined, верно ? Оно вполне себе defined
> - то, что было перед вызовом
Подождите, перед вызовом же ничего не было.
-
KSergey © (20.03.18 09:58) [10]
> Подождите, перед вызовом же ничего не было.
Я же предлагал посмотреть :)
-
Игорь, я таки не понимаю про мусор на стеке, которым "проинициализировали".
Если написано
function НужнаяФункция(): Integer;
var
i: integer;
begin
Result:= i;
end;
то, вообще говоря, значение переменной i тоже вполне себе проинициализировано мусором. Но про это компилятор говорить не стесняется.
Или я что-то всё еще не понимаю?
-
Про собственные типы данных и отсутствие указанного варнинга наверное тут такое соображение: если я проинициализировал 1 поле выходной структуры - это уже можно считать, что значение присвоено, или еще нет? и чтобы над этой дилеммой не размышлять - для пользоватльских типов такой варнинг и не работает...
-
KSergey © (23.03.18 13:30) [12]
В функцию, которая возвращает сложный тип, результат передается извне. Неявно. Компилятор внутри функции не может знать, проинициализирован он или нет.
-
чудесное предположение.
особенно если вспомнить что ни одно из полей рекорда не имеет ни малейшего отношения к "Return value of function"
-
надо писать так -
type TMyRec = ..... end;
PMyRec = ^TMyRec;
function GetXxx(...): PMyRec;
begin
end;
т.е. создавать переменные самому, не надеяться на "компилер маджик", или не создавать... тогда и сообщения появятся.
> Или я что-то всё еще не понимаю?
переменная и ее значение не одно и тоже.
p.s.
function GetXxx(...): string;
begin
end;
тоже не предупреждает, хотя тип не пользовательский (не надо зацикливаться на типе).
-
> надо писать так -
>
> type TMyRec = ..... end;
> PMyRec = ^TMyRec;
Это вредный совет
-
> Игорь Шевченко © (23.03.18 13:47) [14]
> В функцию, которая возвращает сложный тип, результат передается
> извне. Неявно. Компилятор внутри функции не может знать,
> проинициализирован он или нет.
Вот теперь до меня дошло, что было написано выше.
Спасибо.
Пользуясь случаем, передаю выдумщикам сего чуда отдельный пламенный привет. Уверен, они не замёрзнут.
-
> sniknik © (23.03.18 15:29) [16]
> function GetXxx(...): PMyRec;
> begin
> end;
Возвращать из функции указатель на созданный внутри неё объект - ой.
-
> Возвращать из функции указатель на созданный внутри неё
> объект - ой.
Любой конструктор возвращает "созданный внутри функции объект" и как-то ничего, программы работают :)
-
> Возвращать из функции указатель на созданный внутри неё объект - ой.
хочешь предупреждение? - возвращая явно тобой созданное. надеешься на "компилер маджик", когда за тебя дельфи создаст объект... забудь про предупреждение, т.к. система создать не забудет и вернет инициализированное, всегда.
-
> sniknik © (02.04.18 11:49) [21]
> хочешь предупреждение? - возвращая явно тобой созданное.
> надеешься на "компилер маджик",
Да кто ж знал, что в таком простом месте внезапно "компилер маджик"??
-
а то, что не приходится выделять память под строки/объекты в других местах не удивляет? место неважно.