Вот ещё баг, полученный упрощением предыдущего:
Код:
<* GENPTRINIT+ *> (* Make sure local pointers are initialized, including RECORD fields. *)
<* PROCINLINE+ *> (* Allow procedure inlining. *)
<* CHANGESYM+ *>
<* MAIN+ *>
MODULE Main;
(* ------------------------------------------------------------------------
* (C) 2012 by Alexander Iljin
* ------------------------------------------------------------------------ *)
IMPORT
Out;
PROCEDURE InitModule; (* This procedure will be inlined. *)
VAR
ptr: POINTER TO ARRAY OF CHAR;
BEGIN
(* Since GENPTRINIT is ON, the field wr.ptr must be set NIL, but that
* does not happen if the procedure is inlined. The compiler simply does
* not generate the initialization code (typically that would be a "push 0"
* instruction), and whatever is in the stack is left in the pointer field.
* In real-life programs this leads to random 'invalid location' traps. *)
IF ptr # NIL THEN
Out.String('Error!');
ELSE
Out.String('Test passed.');
END;
END InitModule;
BEGIN
InitModule;
END Main.
Здесь вместо стекового RECORD имеем обычную локальную переменную-указатель. При включенном GENPTRINIT её значение должно быть однозначно определено: NIL. Однако, XDS 2.50, 2.51 и 2.60 beta при запуске показывают совершенно неожиданный результат: "#RTS: unhandled exception #3: invalid location".
Оказывается, компилятор, не долго думая, просто заменяет код процедуры на пару инструкций:
Код:
push 3
call X2C_TRAP_F
По его мнению, тут однозначно будет трап, так что даже нет смысла генерировать код. А ведь код вполне осмысленный. Более того, нет даже попытки разыменования указателя ptr, идёт только лишь сравнение его с NIL. Трапу просто неоткуда взяться.
Интересно, что XDS 2.50 и 2.51 выдают при компиляции предупреждение
Код:
* [Main.ob2 30.07 W304]
* possibly used before definition "ptr"
IF $ptr # NIL THEN
Это вполне справедливо, хотя при включенном GENPTRINIT этого предупреждения тоже быть не должно.
А XDS 2.60 beta уже дополнительно предупреждает о том нехорошем действии, что он задумал:
Код:
* [Main.ob2 30.11 W915]
* invalidLocation exception will be raised here
IF ptr $# NIL THEN
Да, он собирается поднять там исключение. Почему? Зачем? Разыменования указателя как не было, так и нет.
PS: 2.50 и 2.51 тоже выдают предупреждение о том, что будет исключение, но только если отключить PROCINLINE.