Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6203609
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T04:56:45+00:00 2026-05-24T04:56:45+00:00

Apparently, Constrained Execution Region guarantees do not apply to iterators (probably because of how

  • 0

Apparently, Constrained Execution Region guarantees do not apply to iterators (probably because of how they are implemented and all), but is this a bug or by design? [See the example below.]

i.e. What are the rules on CERs being used with iterators?

using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;

class Program
{
    static bool cerWorked;
    static void Main(string[] args)
    {
        try
        {
            cerWorked = true;
            foreach (var v in Iterate()) { }
        }
        catch { System.Console.WriteLine(cerWorked); }
        System.Console.ReadKey();
    }

    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    unsafe static void StackOverflow()
    {
        Big big;
        big.Bytes[int.MaxValue - 1] = 1;
    }

    static System.Collections.Generic.IEnumerable<int> Iterate()
    {
        RuntimeHelpers.PrepareConstrainedRegions();
        try { cerWorked = false; yield return 5; }
        finally { StackOverflow(); }
    }

    unsafe struct Big { public fixed byte Bytes[int.MaxValue]; }
}

(Code mostly stolen from here.)

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T04:56:46+00:00Added an answer on May 24, 2026 at 4:56 am

    Well, I do not know if this a bug or just a really weird edge case in which CERs were not designed to handle.

    So here is the pertinent code.

    private static IEnumerable<int> Iterate()
    {
        RuntimeHelpers.PrepareConstrainedRegions();
        try { cerWorked = false; yield return 5; }
        finally { StackOverflow(); }
    }
    

    When this gets compiled and we attempt to decompile it into C# with Reflector we get this.

    private static IEnumerable<int> Iterate()
    {
        RuntimeHelpers.PrepareConstrainedRegions();
        cerWorked = false;
        yield return 5;
    }
    

    Now wait just a second! Reflector has this all screwed up. This is what the IL actually looks like.

    .method private hidebysig static class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> Iterate() cil managed
    {
        .maxstack 2
        .locals init (
            [0] class Sandbox.Program/<Iterate>d__1 d__,
            [1] class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> enumerable)
        L_0000: ldc.i4.s -2
        L_0002: newobj instance void Sandbox.Program/<Iterate>d__1::.ctor(int32)
        L_0007: stloc.0 
        L_0008: ldloc.0 
        L_0009: stloc.1 
        L_000a: br.s L_000c
        L_000c: ldloc.1 
        L_000d: ret 
    }
    

    Notice that there is, in fact, no call to PrepareConstrainedRegions despite what Reflector says. So where is it lurking? Well, it is right there in the auto generated IEnumerator‘s MoveNext method. This time Reflector gets it right.

    private bool MoveNext()
    {
        try
        {
            switch (this.<>1__state)
            {
                case 0:
                    this.<>1__state = -1;
                    RuntimeHelpers.PrepareConstrainedRegions();
                    this.<>1__state = 1;
                    Program.cerWorked = false;
                    this.<>2__current = 5;
                    this.<>1__state = 2;
                    return true;
    
                case 2:
                    this.<>1__state = 1;
                    this.<>m__Finally2();
                    break;
            }
            return false;
        }
        fault
        {
            this.System.IDisposable.Dispose();
        }
    }
    

    And where did that call to StackOverflow mysteriously move to? Right inside the m_Finally2() method.

    private void <>m__Finally2()
    {
        this.<>1__state = -1;
        Program.StackOverflow();
    }
    

    So lets examine this a little more closely. We now have our PrepareConstainedRegions call inside a try block instead of outside where it should be. And our StackOverflow call has moved from a finally block to a try block.

    According to the documentation PrepareConstrainedRegions must immediatly precede the try block. So the assumption is that it is ineffective if placed anywhere else.

    But, even if the C# compiler got that part right things would be still be screwed up because try blocks are not constrained. Only catch, finally, and fault blocks are. And guess what? That StackOverflow call got moved from a finally block to a try block!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Apparently you can easily obtain a client IP address in WCF 3.5 but not
I have this sql: ALTER TABLE dbo.ChannelPlayerSkins DROP CONSTRAINT FK_ChannelPlayerSkins_Channels but apparently, on some
Apparently, this call to window.open is not valid under Internet Explorer. The Javascript code
Apparently using the URL is no good - why is this the case, and
Apparently xrange is faster but I have no idea why it's faster (and no
Apparently, they're confusing. Is that seriously the reason? Can you think of any others?
apparently it works Can you name reasons beyond good practices not to give these
Apparently this problem comes up fairly often, after reading Regular expression to detect semi-colon
I tried using the following but apparently it's invalid SQL: CREATE OR REPLACE TRIGGER
Apparently, x86 (and probably a lot of other instruction sets) put both the quotient

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.