-
В 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;
Возвращать из функции указатель на созданный внутри неё объект - ой.
|