This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/AM5726: How to prevent out-of-order execution of the code within an if statement

Part Number: AM5726

Tool/software: TI C/C++ Compiler

Hello,

I'm writing today to ask how I should best handle a situation where my code is causing a memory protection fault because it is dereferencing a null pointer. Here is the simple pseudo-code of my function:

value = 0;

if (guardFlagIsSet)
{
    // Perform operation that dereferences a pointer
    value = *pointer;
}

return value;

The guard flag is not set until the pointer is initialized, but this function is called both before and after that happens during the life of my system. What I am seeing is that due to compiler optimization, the assembly is dereferencing the pointer and reading the memory "at the same time" that it is evaluating the guard flag. If the guard flag ends up being false, then the value read from memory is ultimately not used. So the behavior is certainly correct, but I end up with a memory protection fault on the DSP because the uninitialized pointer is read.

My guess is that there are a few different ways to solve this problem; perhaps by making the guard flag volatile (although I'm not sure if that is guaranteed to work), perhaps with a pragma. I'd like to ask for a recommendation from someone who is very familiar with the TI compiler. I want to make sure that the solution is relatively future-proof, so that when I upgrade compiler versions in the future it is not likely to return. Thanks in advance!

Best regards,
Dave

  • I think the easiest is to depend on C's "short circuiting":

    if (pointer && guardFlag is Set)

    Once the compiler knows that the rest of the logical expression is moot, it will just set the value and move on. In this case, if pointer is invalid (logical 0), the compiler knows that the value of the expression has to be zero and moves on. This behavior was put into C just for this case.

  • , thanks for your response. Just to be clear, my "guard flag" is not set unless the pointer has already been initialized to a non-zero value. Would you expect any of the following functions to behave differently than each other, assuming that guardFlag and pointer are both zero?

    Function 1:

    value = 0;

    if (guardFlag)
    {
        // Perform operation that dereferences a pointer
        value = *pointer;
    }

    return value;

    Function 2:

    value = 0;

    if (pointer)
    {
        // Perform operation that dereferences a pointer
        value = *pointer;
    }

    return value;

    Function 3:

    value = 0;

    if (pointer && guardFlag)
    {
        // Perform operation that dereferences a pointer
        value = *pointer;
    }

    return value;

  • Assuming that guardFlag is a global, and that its value is set in a manner known to the compiler - i.e., not in an ISR - then they should all be the same.

  • OK, that's what I thought as well. So in my code (function 1), what is happening is the compiler is reordering the read of *pointer so that it can be performed in parallel with the evaluation of guardFlag. In the end, the value of *pointer, which is read into a register, is not assigned into value because guardFlag is zero; but nonetheless, the DSP records a memory protection fault because the null *pointer was read.

  • Unless TI chimes in, I suggest you go with the C idiom of if(p).

  • This ...

    Butters said:
    I end up with a memory protection fault on the DSP because the uninitialized pointer is read.

    ... seems like a bug in the compiler.  For the source file which generates this problem assembly code, please follow the directions in the article How to Submit a Compiler Test Case.

    Thanks and regards,

    -George

  • Hello!

    Could you please share to public, which CGT version behaves this way.

    Thanks.

  • , thank you, I am sending the preprocessed file and compiler options to you via private message.

    The CGT version that I am using is TI G3 TMS320C6x C/C++ Codegen PC v8.3.5.

  • Thank you for submitting a test case.  I can reproduce the problem.  I filed the entry EXT_EP-9945 to have this investigated.  You are welcome to follow it with the link below in my signature.

    Thanks and regards,

    -George

  • Thanks, George. I'm glad to see that TI has an external JIRA interface now; that should be very helpful to us customers as we try to keep informed about issues like this.

    Have a great day,
    Dave