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/OMAP3530: Problem with sprintf and 8-byte inputs

Part Number: OMAP3530

Tool/software: TI C/C++ Compiler

I seem to be having some trouble when passing 8-byte variables into sprintf. Here is the excerpted code that seems to lead to the problem (This is not quite a working example but shows the relevant calls):

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

void my_func(void)
{
union {
        unsigned char bytes[8];
        unsigned long long int big_int;
        unsigned int reg_int[2];
        double dbl;
    } foo;

static unsigned char msg1[256], msg2[256], msg3[256];

foo.dbl = 0.1;

sprintf(msg1,"Dbl: %f", foo.dbl);
sprintf(msg2, "Long: %llx", foo.big_int);
sprintf(msg3, "Bytes: %x%x%x%x%x%x%x%x", foo.bytes[0], foo.bytes[1], foo.bytes[2], foo.bytes[3], foo.bytes[4], foo.bytes[5], foo.bytes[6], foo.bytes[7]);

}

The three strings I get are:

msg1: Dbl: 0.000000

msg2: Long: 202020203fb99999

msg3: Bytes: 9a9999999999b93f

The second half of the long long string, ie., 0x3fb99999 is actually correct (but byte-reversed as expected), but the high order (first four) bytes are not. It looks like something else is getting put onto the stack for the printf call. The bytes from MSG3 are correct.

 

Some notes:

  • I have plenty of stack and heap space allocated.
  • I have the --printf_support = full flag set in the compiler setup
  • I have tried gcc, c99 and c89 compiler flags.
  • I have tried all LTS compiler versions between 15.12.7 and 18.1.2
  • I have tried both sprintf and snprintf  calls and there is no difference in the result.
  • 32-Bit integers will print without problems.
  • Single-Precision floats give the same problem (I suspect they are promoted to doubles per the C99 standard)

Any thoughts?

  • Please show the build options used when compiling and linking.  If it is easier, you are welcome to capture all the compile and link commands in a text file, and attach it to your next post.

    Thanks and regards,

    -George

  • Here are the compiler flags (some project-specific defines and include directories removed):

    "C:/ti/ccsv7/tools/compiler/ti-cgt-arm_18.1.2.LTS/bin/armcl" -mv7A8 --code_state=32 --float_support=VFPv3 -me -O4 --opt_for_speed=5 --fp_mode=strict  --include_path="C:/ti/ccsv7/tools/compiler/ti-cgt-arm_18.1.2.LTS/include"  -g --c99 --relaxed_ansi --printf_support=full --diag_warning=225 --neon --enum_type=packed --abi=eabi --fp_reassoc=off --std_lib_func_defined --asm_listing --cross_reference --gen_opt_info=2 --preproc_with_compile --preproc_dependency="myfile.d_raw"  "myfile.c"

    And the linker flags (similar edits for brevity):

    "C:/ti/ccsv7/tools/compiler/ti-cgt-arm_18.1.2.LTS/bin/armcl" -mv7A8 --code_state=32 --float_support=VFPv3 -me -O4 --opt_for_speed=5 --fp_mode=strict  -g --c99 --relaxed_ansi --printf_support=full --diag_warning=225 --neon --enum_type=packed --abi=eabi --fp_reassoc=off --std_lib_func_defined --asm_listing --cross_reference --gen_opt_info=2 -z -m"my_project.map" -i"C:/ti/ccsv7/tools/compiler/ti-cgt-arm_18.1.2.LTS/lib" -i"C:/ti/ccsv7/tools/compiler/ti-cgt-arm_18.1.2.LTS/include" --reread_libs --warn_sections --absolute_exe --xml_link_info="my_project_linkInfo.xml" --no_symtable --cinit_compression=rle --rom_model -o "my_project.out" <<ALL THE OBJECT FILES>> "ap-link.cmd"   -llibc.a

  • Unfortunately, we are unable to reproduce the problem.  

    It appears what you sent is a cut down of the problem source code.  And by simplifying things, you unintentionally removed part of what causes the problem.  Please submit a more complete test case.  In this case, it would be best to send in the code for the function which contains the problem calls to sprintf.  For the source file that contains that function, please submit a test case as described in the article How to Submit a Compiler Test Case.  Please indicate which calls to sprintf return incorrect results.  Don't worry about whether we can run the code.  We can often spot the problem by inspecting the compiler generated assembly code.

    Thanks and regards,

    -George

  • I apologize for the delay.

    Thank you for sending in a more complete test case by private message.  

    George Mock said:
    Don't worry about whether we can run the code.  We can often spot the problem by inspecting the compiler generated assembly code.

    Unfortunately, this time, I'm wrong.  We are unable to spot the problem by inspecting the compiler generated assembly code.  The cause of the problem must be very subtle, or requires the combination of some things we cannot see, or something like that. 

    This forces me to ask you for a test case which runs and demonstrates the problem.  The smaller it is, the better.  That said, do limit your effort in cutting it down.  We appreciate what you have done so far, and I'm sorry I have to ask for more.  I presume the test case will be in the form of a CCS project.  Package it into a zip file as described in the article Project Sharing, then send it by private message, just like you did with your previous test case.

    Thanks and regards,

    -George

  • I hope you have had a chance to get that test case together.

    Thanks and regards,

    -George

  • Something very strange seems to be going on.  I am unable to reproduce anything like those symptoms.  I have modified your test case to emit a lot more information about what's going on.  Please run this and tell us the output.  How are you examining msg1, msg2, and msg3?  I presume it is in the CCS debugger in the watch window?  What does it look like from the memory view window?

    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>

    #include <stdarg.h>
    #include <assert.h>

    void v_d(int x, ...)
    {
        double r;
        va_list l;
        va_start(l, x);
        r = va_arg(l, double);
        va_end(l);
        printf("v_ll got %f\n", r);
    }

    void v_ll(int x, ...)
    {
        unsigned long long r;
        va_list l;
        va_start(l, x);
        r = va_arg(l, unsigned long long);
        va_end(l);
        printf("v_ll got %llx\n", r);
    }

    void my_func(void)
    {
        union {
            unsigned char bytes[8];
            unsigned long long int big_int;
            unsigned int reg_int[2];
            double dbl;
        } foo;

        static char msg1[256], msg2[256], msg3[256];

        foo.dbl = 0.1;

        sprintf(msg1,"Dbl: %f", foo.dbl);
        sprintf(msg2, "Long: %llx", foo.big_int);
        sprintf(msg3, "Bytes: %x%x%x%x%x%x%x%x",
                foo.bytes[0], foo.bytes[1], foo.bytes[2], foo.bytes[3],
                foo.bytes[4], foo.bytes[5], foo.bytes[6], foo.bytes[7]);

        printf("[%s]\n", msg1);
        printf("[%s]\n", msg2);
        printf("[%s]\n", msg3);

    #if __little_endian__
        printf("I am little endian!\n");
    #elif __big_endian__
        printf("I am big endian!\n");
    #else
        #error unknown endianness
    #endif

        printf("&foo == %p\n", &foo);
        printf("sizeof(foo.bytes) == %zu\n", sizeof(foo.bytes));
        printf("sizeof(foo.big_int) == %zu\n", sizeof(foo.big_int));
        printf("sizeof(foo.reg_int) == %zu\n", sizeof(foo.reg_int));
        printf("sizeof(foo.dbl) == %zu\n", sizeof(foo.dbl));

        printf("foo.dbl == %f\n", foo.dbl);
        printf("foo.dbl == %a\n", foo.dbl);
        printf("foo.dbl == %x %x\n", _hi(foo.dbl), _lo(foo.dbl));

        printf("msg1 == %p\n", msg1);
        printf("msg2 == %p\n", msg2);
        printf("msg3 == %p\n", msg3);

        v_ll(0, 0x0123456789abcdef);
        v_d(0, 3.1415926);

        static char msg4[256];
        sprintf(msg4, "%016llx", 0x0123456789abcdef);
        assert(msg4[0x0] == '0');
        assert(msg4[0x1] == '1');
        assert(msg4[0x2] == '2');
        assert(msg4[0x3] == '3');
        assert(msg4[0x4] == '4');
        assert(msg4[0x5] == '5');
        assert(msg4[0x6] == '6');
        assert(msg4[0x7] == '7');
        assert(msg4[0x8] == '8');
        assert(msg4[0x9] == '9');
        assert(msg4[0xa] == 'a');
        assert(msg4[0xb] == 'b');
        assert(msg4[0xc] == 'c');
        assert(msg4[0xd] == 'd');
        assert(msg4[0xe] == 'e');
        assert(msg4[0xf] == 'f');

        sprintf(msg4, "%08x%08x", 0x01234567, 0x89abcdef);
        assert(msg4[0x0] == '0');
        assert(msg4[0x1] == '1');
        assert(msg4[0x2] == '2');
        assert(msg4[0x3] == '3');
        assert(msg4[0x4] == '4');
        assert(msg4[0x5] == '5');
        assert(msg4[0x6] == '6');
        assert(msg4[0x7] == '7');
        assert(msg4[0x8] == '8');
        assert(msg4[0x9] == '9');
        assert(msg4[0xa] == 'a');
        assert(msg4[0xb] == 'b');
        assert(msg4[0xc] == 'c');
        assert(msg4[0xd] == 'd');
        assert(msg4[0xe] == 'e');
        assert(msg4[0xf] == 'f');
    }

  • Since it has been a while, I presume you have resolved your problem.  I'd appreciate hearing how you resolved it.

    Thanks and regards,

    -George