05 February 2012

(updated) llvm-gcc strange behavior

Today compiling with XCode 4.2.1 ... i found this.. the syntax is right... ¿have the switch instruction a limitation about this? YES


 ARM and x86 architecture supports 'nop' instruction... the use is safe for your code:


In Switch-Case statement, you can't declare variables inside, the 'cases' are translated to jump to memory address (some bytes after normally) in case of jump, the stack is not re-framed, like a simple "goto" basic instruction ("jmp" in asembler) is used to go to the correct memory address, when this instruction ends, the stack is returned "as is", with some bytes more of allocations in them, causing unexpected BAD_ACCESS & other low level errors. 

Never allocate in switch case ;-) "learn from mistakes"


Posted at BinaryCell

1 comment:

  1. This is a weird thing caused by the switch-statement in C.

    To understand the reason we need to see how the (only relevant for the current discussion) statements are defined in the C language:

    select-statement → if (expression) statement
    → if (expression) statement else statement
    → switch (expression) statement

    jump-statement → goto identifier ;
    → continue ;
    → break ;
    → return ;
    → return expression ;

    labeled-statement → identifier : statement
    → case expression : statement
    → default: statement

    compound-statement → { statement-seq }

    (Here statement-seq means a sequence of statements of C, including but not limiting to all those shown above)

    switch is normally used like this

    switch (e)
    {
    case A:
    statement1;
    statement2
    break;
    }

    Note two things in the code above: there is a compound-statement right after the switch (otherwise you would only be able to write a single statement!). Thus, inside a compound statement there is a statement-seq (a sequence of statements). The first one, is, interestingly, a labeled-statement, the remaining ones are two statements and then there is a break statement.

    Do you see the pattern. That 'case A' is only related to statement1. statement2 is just the next statement inside the compound-statement we usually write after a switch.

    This leads to strange things like

    switch (e)
    {
    case A:
    int tmp = ... ;
    statement1;
    break;
    case B:
    int tmp = ...; // ← error! tmp redeclared
    statement2;
    }

    which makes sense, since you wrote something that conceptually is like

    {
    A: int tmp = ...; // A here would be a label-name
    statement1;
    goto END; // This would be the break;
    B: int tmp = ...; // B here would be a label-name
    statement2;
    END:
    }

    so to solve this problem you should do

    switch (e)
    {
    case A:
    {
    // Open here a compound-statement
    int tmp = ...;
    break; // Or right after the closing } of the compound-statement, it doesn't matter
    }
    // You could put the break here as well
    case B:
    {
    // Open here a compound-statement
    int tmp = ...; // Look ma, no problems!
    break;
    }
    ...
    }


    And you know what? Such weird thing is present in C++ (obviously) and Java as well!

    ReplyDelete


Disclaimer: In no event shall the blog owner, be liable for any damages, including without limitation, special, indirect or consequential damages, or any damages, whatsoever resulting from access or use, or inability to access or use this Website or arising out of any materials, information, qualifications or recommendations on this Website.