Цитата:
Сообщение от
Logger
Кстати получается что все Exists методы на таблицах надо править теперь ? Или будет нормально работать ?
Вопрос, конечно, интересный

Тесты показывают, что описанный глюк возникает (по крайней мере, в AX2009) в следующих случаях:
- присвоение переменной типа boolean значения типа Int64 с нулевыми младшими 32-мя (а не 8-ю, как утверждалось в исходном сообщении) разрядами;
- присвоение переменной другого перечислимого типа значения типа Int/Int64 с нулевыми младшими 8-ю разрядами;
Если, к примеру, значение Int64 используется в выражении как операнд логической функции, например
X++:
boolean ret = _salesId && salesTable.RecId;
то глюк
не воспроизводится, равно как и при использовании Int64 в операторе if, в т.ч. в форме тернарного оператора ? :
X++:
boolean ret = record.RecId ? true : false;
Но самое интересное то, что ядро
не производит приведение типа для возвращаемого значения функции, т.е. для функции вида
X++:
boolean func()
{
// ...
return record.RecId
}
приведение типа будет произведено лишь при вычислении выражения, где непосредственно используется возвращаемое функцией значение, а не перед возвратом управления из нее. Это можно легко увидеть на таком примере:
X++:
Int64 i;
boolean test()
{
return 0x7fffffff00000000;
}
;
i = test();
info( strfmt('%1', i) );
Таким образом, если функция с типом возвращаемого значения boolean на самом деле возвращает значение типа Int64, то возникнет ли описанный в этой теме глюк или нет, будет зависеть от характера использования значения функции. В случае
глюк не возникнет, а вот поведение такого кода
X++:
boolean b = test();
if (b) // ...
будет зависеть от того, какое именно ненулевое число вернет test() под видом boolean. В общем, лучше, конечно, сомнительные места в методах exist() исправить; для поиска таких мест был написан простенький job, выводящий список табличных методов exist() с "сомнительным" использованием значений RecId. Сразу скажу, что у job'а наблюдаются ложные срабатывания, тем не менее, в том же приложении ax2009 было найдено 63 потенциально "проблемных" табличных методов exist() (на sys-слое), из которых минимум половина нуждается в исправлении с учетом описанного глюка - во всяком случае, покуда не вышло исправленное ядро.
X++:
#define.RecIdPattern ('[.]RecId')
#define.RecIdNEZeroPattern ('[.]RecId[ ]*!=[ ]*0')
UtilElements utilElements;
UtilEntryLevel currentLayer;
TreeNodePath treeNodePath;
TreeNode treeNode;
Source sourceCode;
Set setOfMethods;
Counter n;
;
setOfMethods = new Set( Types::String );
currentLayer = currentAOLayer();
while select utilElements
order by parentId, utilLevel
where utilElements.recordType == UtilElementType::TableStaticMethod
&& utilElements.utilLevel <= currentLayer
&& utilElements.name like '*exist*'
&& !( utilElements.name like '*txtNotExist*' )
{
treeNodePath = xUtilElements::getNodePath( utilElements );
if (!setOfMethods.in( treeNodePath ))
{
treeNode = TreeNode::findNode( treeNodePath );
sourceCode = SysUtil::unpackSource( treeNode.AOTgetSource() );
if ( match( #RecIdPattern, sourceCode )
&& !match( #RecIdNEZeroPattern, sourceCode )
)
{
n++;
setOfMethods.add( treeNodePath );
info( strfmt( @"%1::%2() (%3)", tableid2name(utilElements.parentId), utilElements.name, utilElements.utilLevel ), '', SysInfoAction_Editor::newOpen( treeNodePath ) );
}
}
}
if (n)
{
info( strfmt( "@SYS26824", n ) );
}
else
{
warning( "@SYS4205" );
}