Variable optimized away by compiler

I started debugging some code attempting to find my mistake. When I attempt to p tlEntries from the debugger I get the

<variable optimized away by compiler>

  • Storyboards vs. doing it in code
  • Question on View Controller's view
  • Pause Stop watch timer in iPhone?
  • How to upload/share video on Facebook ?
  • TCP Socket Programming in iOS. Server Client Response
  • iOS UIImageView scaling image down produces aliased image on iPad 2
  • message while stopped on the if statement. The following is my code:

    NSArray *tlEntries = [[NSArray alloc] initWithArray:[self fetchJSONValueForURL:url]];
    for (NSDictionary *info in tlEntries) 
    {
        if ([info objectForKey:@"screen_name"] != nil)
             NSLog(@"Found %@ in the timeline", [info objectForKey:@"screen_name"]);
    }
    

    Earlier debugging gives me confidence the URL is indeed returning a valid NSArray, but I don’t understand why tlEntries is being “optimized away”.

    4 Solutions Collect From Internet About “Variable optimized away by compiler”

    The compiler probably noticed that you only use tlEntries twice in the beginning, and don’t use it at all in the loop. Loops create an enumeration object instead of keeping a reference to the container object, if I remember correctly. So tlEntries should be valid for the first line but then gone for the rest.

    Idea: You can force the compiler to keep it by using tlEntries somewhere later in the function. Something like

    NSPrint(@"IGNORE THIS LINE %p", tlEntries);
    

    Better idea: You can set the optimization to -O0. This is highly recommended for debugging code. It should be set to -O0 automatically if you use the “Debug” instead of “Release” builds, but you can change that.

    The proper solution is to declare the variable in a different way as follows:

    volatile NSArray *tlEntries;
    

    Indeed, the volatile keyword is used exactly to inform the compiler that it must not try to optimize the code related to that variable in any way.
    Kind regards.

    When compiler optimizations are enabled, variables are frequently “optimized away” by placing them in registers or other tricks such as statement re-ordering. If you are using any -O flag other than -O0 then this can take place.

    I don’t think that adding additional references to the variable in your code are going to prevent this from happening. (If anything, the compiler may try even harder since the potential gain from optimizing it away is greater.)

    As a temporary workaround, you can declare the variable “volatile”. This isn’t generally a good long-term solution because it prevents the compiler from performing any optimizations involving that variable.

    Another workaround is to use good old-fashioned logging. Something like:

    NSLog(@"Entries initialized as: %@", tlEntries);
    

    Finally, you can also compile with -O0. Many people recommend this for the Debug project profile. Although it prevents optimization it makes debugging much easier. Stepping through statements is actually predictable, and variables can be viewed. Unfortunately it has what I consider a rather nasty side-effect with the version of gcc that Apple ships: when -O0 is in effect you can’t get warnings about using variables prior to initialization. (I personally find this warning useful enough that I’m willing to suffer the pain of debugging being less convenient.)

    P.S. You have a memory leak in the snippet posted; for clarity an additional line should be added:

    [tlEntries release];
    

    Assuming that you never use this variable later on (which seems reasonable if the compiler optimized it away), one very important way you could use to solve the issue (similar to Dietrich’s example, though better for your program) is to do a:

    [tlEntries release];
    

    Otherwise, you will definitely leak that memory away. This will make the compiler see the object used later (as does the NSPrint) so it will not be optimized out.