Thread: Different behaviour of same code between armhf and x86

  1. #1
    Registered User
    Join Date
    Jan 2017
    Posts
    13

    Different behaviour of same code between armhf and x86

    I was doing some code on armhf architecture (gcc 4.9.2 and 4.6.3) and noticed this behaviour that I could not reprpduce on x86 (gcc 4.9.2), please note the code and output below.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    
    //Returns substring using given index
    int retSubstring(char *myStr, size_t start, size_t end, char *subStri){
        if(end > start){
            char *s = &myStr[start];
            char *e = &myStr[end + 1];
    
            printf("_____before memcpy: '%s', size: %i\n", subStri, strlen(subStri));
            memcpy(subStri, s, e - s);
            printf("_____after memcpy: '%s', size: %i\n\n", subStri, strlen(subStri));
            return 0;
        }else{
            printf("retSubstring error: end is greater than start.\n");
            return 1;
        }
    }
    
    int main(void){
       int start = 8;
       int end= 37;
       
       char myStr[] = "1-2-1-2-1-2-1-2-1-2-1-2-1-2-1-2-1-2-1-2-1-2-1";
       
       start = 0;
       end= 10;
       char * subStr2 = malloc(sizeof(char) * (end - start));
       retSubstring(myStr, start, end, subStr2);
       free(subStr2);
       
       start = 20;
       end= 25;
       char * subStr3 = malloc(sizeof(char) * (end - start));
       retSubstring(myStr, start, end, subStr3);
       free(subStr3);
    }
    Above code outputs:
    _____before memcpy: '', size: 0
    _____after memcpy: '1-2-1-2-1-2', size: 11

    _____before memcpy: '', size: 0
    _____after memcpy: '1-2-1-2-1-2', size: 11
    Remark 1: The expected size of the second call after memcpy would be 6.

    Remark 2: The size is indeed 6 in the following two cases:
    1. when compiled without the calls to "free(subStr2)" and "free(subStr3)" (ie: commented out)
    2. when compiled on x86 architecture also the following result is as expected:

    _____before memcpy: '', size: 0
    _____after memcpy: '1-2-1-2-1-2', size: 11

    _____before memcpy: '', size: 0
    _____after memcpy: '1-2-1-', size: 6
    Any ideas what is causing this?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,662
    Yes, you're using strlen() to determine a size, which is wrong.

    strlen() takes your pointer and just walks through memory (right off the end of your substring) and keeps going until it lucks into a \0.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jan 2017
    Posts
    13
    Thanks for your comment Salem, but your reply does not apply to my question.

    Just to be sure I removed the strlen from the code, and the issue persists.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,662
    So how are you measuring length if you're not using strlen?
    Post your latest code.

    > Remark 2: The size is indeed 6 in the following two cases:
    > 1. when compiled without the calls to "free(subStr2)" and "free(subStr3)" (ie: commented out)
    Like I said, pure dumb luck.
    Not calling free means getting a fresh block of memory with (quite likely) a handy \0 just in the right place to convince you that you're golden.

    By calling free, the second malloc re-uses the memory of the first malloc - complete with the long string from last time - but the difference being there is no handy \0 in the right place for you to claim success.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Jan 2017
    Posts
    13
    That explanation makes sense to me now, regarding the strlen.. thanks!

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,662
    Example
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <unistd.h>
    
    void dumpMem ( void *base, size_t len ) {
      unsigned char *b = base;
      printf("%p: ", base);
      for ( size_t i = 0 ; i < len ; i++ ) {
        printf("%02x ", b[i] );
      }
      printf("\n");
      printf("%p: ", base);
      for ( size_t i = 0 ; i < len ; i++ ) {
        printf("%c  ", isprint(b[i]) ? b[i] : '.');
      }
      printf("\n");
    }
    //Returns substring using given index
    int retSubstring(char *myStr, size_t start, size_t end, char *subStri){
        if(end > start){
            char *s = &myStr[start];
            char *e = &myStr[end + 1];
    
            printf("_____before memcpy: '%s', size: %zd\n", subStri, e - s);
            dumpMem(subStri-8,(e-s)+16); // the memory, and a bit around it
            memcpy(subStri, s, e - s);
            printf("_____after memcpy: '%s', size: %zd\n\n", subStri, e - s);
            dumpMem(subStri-8,(e-s)+16); // the memory, and a bit around it
            return 0;
        }else{
            printf("retSubstring error: end is greater than start.\n");
            return 1;
        }
    }
    
    int main(void){
       int start = 8;
       int end= 37;
    
       char myStr[] = "1-2-1-2-1-2-1-2-1-2-1-2-1-2-1-2-1-2-1-2-1-2-1";
    
       start = 0;
       end= 10;
       char * subStr2 = malloc(sizeof(char) * (end - start));
       retSubstring(myStr, start, end, subStr2);
       free(subStr2);
    
       start = 20;
       end= 25;
       char * subStr3 = malloc(sizeof(char) * (end - start));
       retSubstring(myStr, start, end, subStr3);
       free(subStr3);
    }
    
    $ ./a.out 
    _____before memcpy: '', size: 11
    0x1d21008: 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    0x1d21008: !  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
    _____after memcpy: '1-2-1-2-1-2', size: 11
    
    0x1d21008: 21 00 00 00 00 00 00 00 31 2d 32 2d 31 2d 32 2d 31 2d 32 00 00 00 00 00 00 00 00 
    0x1d21008: !  .  .  .  .  .  .  .  1  -  2  -  1  -  2  -  1  -  2  .  .  .  .  .  .  .  .  
    _____before memcpy: '', size: 6
    0x1d21008: 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 31 2d 32 00 00 00 
    0x1d21008: !  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  1  -  2  .  .  .  
    _____after memcpy: '1-2-1-', size: 6
    
    0x1d21008: 21 00 00 00 00 00 00 00 31 2d 32 2d 31 2d 00 00 31 2d 32 00 00 00 
    0x1d21008: !  .  .  .  .  .  .  .  1  -  2  -  1  -  .  .  1  -  2  .  .  .
    Two things to note here:
    1. The second malloc gets the same address as the first malloc, because you called free.
    2. The second malloc cleaned out the memory from the previous use (though it's under no obligation to do so). Note that the amount cleared out is (on my system) rounded up to the next multiple of 8 bytes.

    I suspect that if you tried your old code (using strlen) using end= 27; instead of 25 (so you have 8 bytes to copy), then you might just notice some weird stuff on other platforms as well.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Does the following code show undefined behaviour ?
    By manasij7479 in forum C++ Programming
    Replies: 32
    Last Post: 10-15-2011, 11:44 AM
  2. weird behaviour with abs()
    By crazyinlove in forum C Programming
    Replies: 19
    Last Post: 02-28-2010, 12:58 AM
  3. cache behaviour
    By cyberfish in forum C++ Programming
    Replies: 10
    Last Post: 12-25-2008, 07:48 AM
  4. Unexpected behaviour
    By fnoyan in forum C++ Programming
    Replies: 5
    Last Post: 03-05-2005, 09:45 AM
  5. strange behaviour.......
    By surdy in forum C Programming
    Replies: 2
    Last Post: 05-01-2004, 11:50 AM

Tags for this Thread