:: Не фоксом единым
последовательность выполнения
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
В одном из тестов нарвался на примерно такой код:

class Program
{
static string myFunc(string str)
{
try
{
return str;
}
finally
{
Console.WriteLine("Это мы увидим");
str = "Или вот это?";
}
}
static void Main()
{
Console.WriteLine(myFunc("Увидим это?"));
Console.ReadLine();
}
}

В тестах был вопрос - что мы увидим на экране после того, как программа отработает. Понятно, что finally выполнится при любом раскладе. Т.е. сообщение "Это мы увидим" мы обязательно увидим. По сути, вопрос превращается в "что выполнится раньше - блок finally или return"?


А у меня вопрос - для такого случая последовательность выполнения где то регламентирована? Полез в msdn.microsoft.com - ответа не нашёл. Может, в какой то другой статье есть ответ?



Исправлено 2 раз(а). Последнее : S-type, 22.02.17 00:09
Ratings: 0 negative/0 positive
Re: последовательность выполнения
Рома

Сообщений: 1079
Дата регистрации: 06.06.2001
return конечно будет после finally, но неопределенного поведения здесь нет.
Компилятор просто сделает

string result;
try
{
result = str;
}
finally
{
Console.WriteLine("Это мы увидим");
str = "Или вот это?";
}
return result;
Ratings: 0 negative/0 positive
Re: последовательность выполнения
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
Рома
return конечно будет после finally,

Если запустить приведённую мной программу, в консоли высвечивается

Это мы увидим
Увидим это?

Finally каким то образом выполнилось после return-а!
Ratings: 0 negative/0 positive
Re: последовательность выполнения
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
Рома
Компилятор просто сделает

Но, на основании чего он это сделает? Это где то прописано? Почему Return бегает по коду?
Ratings: 0 negative/0 positive
Re: последовательность выполнения
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
Рома
return конечно будет после finally,

Если сделать:

static string myFunc(string str)
{
try
{
return str;
}
finally
{
Console.WriteLine("Это мы увидим");
str = "Или вот это?";
}
Console.WriteLine("Обнаружен недостижимый код"); // предупреждение от компилятора
}

то компилятор выдаёт предупреждение "Обнаружен недостижимый код". Т.е. return после finally реально существует...

Если подумать - на приведённый изначально код компилятор не выдаёт ошибку "Не все ветки кода возвращают значение", хотя оператор return после finally в явном виде не указан.



Исправлено 2 раз(а). Последнее : S-type, 22.02.17 11:44
Ratings: 0 negative/0 positive
Re: последовательность выполнения
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
Почему то вспомнилось:

ДМБ
Видишь суслика? и я не вижу.. А он есть...
Ratings: 0 negative/0 positive
Re: последовательность выполнения
Рома

Сообщений: 1079
Дата регистрации: 06.06.2001
S-type
Но, на основании чего он это сделает? Это где то прописано? Почему Return бегает по коду?

На основании того, что пользователь захотел вернуть вполне конкретное значение.
Если бы у нас не было finally, то можно было бы просто загрузить значение аргумента str на стек и выйти.
В случае с finally не ясно, что будет висеть на стеке после его выполнения (неопределенное поведение)
Поэтому результат сохраняется во временную переменную, из которой он загружается на стек перед выходом.
Ratings: 0 negative/0 positive
Re: последовательность выполнения
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
Сначала

Рома
но неопределенного поведения здесь нет.

Потом

Рома
В случае с finally не ясно, что будет висеть на стеке после его выполнения (неопределенное поведение)

Всё таки, в случае с finally есть "неопределённое поведение"...

Поясню на примере. Предположим, в С есть код:

j = j++;

Всегда можно запустить на выполнение и увидеть результат. Но, в самом стандарте языка С не прописано - что должно выполнится в первую очередь - присваивание или инкремент. Потому, результат может меняться в зависимости от реализации.

Приведённый тобой код иллюстрирует "как это работает". Но, "почему работает именно так?" - не понятно. Это где то "задокументировано", или, "есть как есть"?
Ratings: 0 negative/0 positive
Re: последовательность выполнения
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
S-type
Finally каким то образом выполнилось после return-а!
Нет, на самом деле это return выполнился после блока try-finally (но его выражение "посчиталось" внутри блока!).
finally выполняется всегда при выходе из блока - в частности при выходе из него по return.
Не выполняется он в редких случаях:
- катастрофические/неотлавливаемые (типа StackOverflow, OutOfMemory или ThreadAbort) исключения.
- банально неотловленные/необработанные исключения (то что по сути вываливается "наружу" C# кода - оно тупо убивает приложение).
- Environment.FastFail()


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: последовательность выполнения
Рома

Сообщений: 1079
Дата регистрации: 06.06.2001
S-type
Это где то "задокументировано", или, "есть как есть"?

Задокументировано здесь
ECMA 335 - I.12.4.2.8 Control flow restrictions on protected blocks

В защищенном блоке (try/catch/finnaly) нельзя выполнять инструкцию ret.
Для начала надо выполнить leave (чтобы выполнился код finally)

Например, в VFP return нельзя делать внутри try/catch/finally
C# это разрешает, но делает через временную переменную.
Ratings: 0 negative/0 positive
Re: последовательность выполнения
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
S-type
Всё таки, в случае с finally есть "неопределённое поведение"...
Какое именно? В чём неопределённость?

S-type
Но, в самом стандарте языка С не прописано - что должно выполнится в первую очередь - присваивание или инкремент.
Нет, это совершенно чётко прописано в стандартах языка. Ссылку на ISO нет смысла давать, ибо там только за бабки можно скачать документ
ru.cppreference.com


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: последовательность выполнения
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
Igor Korolyov
S-type
Всё таки, в случае с finally есть "неопределённое поведение"...
Какое именно? В чём неопределённость?
В том, что какие то действия выполняются "за кулисами". А именно - вычисленное значение сначала сохраняется, потом выполняется finally, потом вычисленное значение возвращается. Return выполняется после finally, но возвращается не "текущее значение", а "запомненное раньше". Так понимаю, что это надо "принять как данность".

Igor Korolyov
S-type
Но, в самом стандарте языка С не прописано - что должно выполнится в первую очередь - присваивание или инкремент.
Нет, это совершенно чётко прописано в стандартах языка. Ссылку на ISO нет смысла давать, ибо там только за бабки можно скачать документ
ru.cppreference.com

Согласно стандарта, сначала надо выполнить присваивание, потом - инкремент. Т.е. если i=1 и сделать j=i++, то j=1, а i=2. В случае i=i++ сначала в i надо занести 1, а потом значение в i инкрементировать. А, это не так!



Исправлено 1 раз(а). Последнее : S-type, 22.02.17 14:44
Ratings: 0 negative/0 positive
Re: последовательность выполнения
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
Понимая некоторое скептическое отношение к Википедии, всё таки её упомяну. ru.wikipedia.org ru.wikipedia.org Т.е. есть различие межу Неопределённым поведением и Неуточняемым поведением программы.
Ratings: 0 negative/0 positive
Re: последовательность выполнения
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
Рома
Например, в VFP return нельзя делать внутри try/catch/finally

Очень разумное ограничение. Сразу многое становится ясным и понятным. Видимо, в этом корни моих проблем, что перейдя с VFP на C# ни когда внутри try/catch/finally не использовал return, и на такие проблемы не нарывался.
Ratings: 0 negative/0 positive
Re: последовательность выполнения
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Я тоже обычно не использую return внутри блоков try (в "неявных" блоках типа foreach нет ЯВНЫХ finally или catch). Но даже если бы и использовал, то вряд-ли стал бы в finally писать нечто НЕ связанное с освобождением неуправляемых ресурсов - как и советуют все мануалы
S-type
Согласно стандарта
Так там как раз и описывается поведение (неопределённое, неуточнённое или зависимое от реализации) для этих "хитрых ситуаций". По сути это как раз формализованное описание - можно сказать директива разработчику "так не писать" если он хочет получить strictly conforming program


------------------
WBR, Igor
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 5 (Гостей: 5)

© 2000-2024 Fox Club 
Яндекс.Метрика