January 1st, 2016

Слишком умная оптимизация.

Столкнулся с тем, что дебажная версия работает безукоризненно, а релизная - падает, причём там, где уже всё давно отлажено (казалось бы).
Выяснил, где именно падает, по кускам начал отключать код, ведущий к этому месту и выяснил неожиданное.
Оказалось, что компилятор вдруг решил, что три разныъ вызова одной функции с тремя разными аргументами можно заменить на три вызова этой функции с одним и тем же аргументом, причём не разнеся их по моментам, когда алгоритм обращается к результатам вызова, а почему-то скучковав их вокруг второго (не первого, не последнего). То есть, упрощённо говоря,

for (i=0; i<3; i++)
{
foo(i);
}

превратилось в

foo(2);
foo(2);
foo(2);


Ситуация, конечно, несколько сложнее (там вывод значения символов, находящихся в списке), но менее удивительной она от этого не становится.

Копаю дальше.

Upd: победил, вроде. Лёгкий ореол загадочности всё равно остался (гейзенбаг как он есть - при таких ключах сборки проявляется, при сяких не проявляется, с такой прагмой эффект один, а с другой - другой), но после принудительно-параноидальной правки указателей там, где используется обращение к полям структуры, получил:
Collapse )