0

See below simple example code:

#include <stdio.h>

void dumpmem(unsigned char* p,int len,const char* desc) {
  printf("\nvar:%s\n",desc);
  printf("content:%s\n",p);
  p = p + len - 1;
  for (int i=0;i<len;i++) {
      printf("----%p -> %c(%02x)\n",p,*p,*p);
      p--;
  }
}
#define SIZE 6 
int main(void) {
  unsigned char s1[SIZE];
  unsigned char s2[SIZE];
  unsigned char s3[27] = "abcdefghijklmnopqrstuvwxyz";
  unsigned char* p = (unsigned char*)&s1;
  unsigned char* q = (unsigned char*)(&s1+1);
  dumpmem(s3,27,"s3");   
  sscanf((const char*)s3,"%s",s2);
  dumpmem(s1,SIZE,"s1");   
  dumpmem(s2,SIZE,"s2");   
  dumpmem(s3,27,"s3");   
  return 0;
}

The output is:

var:s3
content:abcdefghijklmnopqrstuvwxyz
----0x7fff5bcc66ea -> (00)
----0x7fff5bcc66e9 -> z(7a)
----0x7fff5bcc66e8 -> y(79)
----0x7fff5bcc66e7 -> x(78)
----0x7fff5bcc66e6 -> w(77)
----0x7fff5bcc66e5 -> v(76)
----0x7fff5bcc66e4 -> u(75)
----0x7fff5bcc66e3 -> t(74)
----0x7fff5bcc66e2 -> s(73)
----0x7fff5bcc66e1 -> r(72)
----0x7fff5bcc66e0 -> q(71)
----0x7fff5bcc66df -> p(70)
----0x7fff5bcc66de -> o(6f)
----0x7fff5bcc66dd -> n(6e)
----0x7fff5bcc66dc -> m(6d)
----0x7fff5bcc66db -> l(6c)
----0x7fff5bcc66da -> k(6b)
----0x7fff5bcc66d9 -> j(6a)
----0x7fff5bcc66d8 -> i(69)
----0x7fff5bcc66d7 -> h(68)
----0x7fff5bcc66d6 -> g(67)
----0x7fff5bcc66d5 -> f(66)
----0x7fff5bcc66d4 -> e(65)
----0x7fff5bcc66d3 -> d(64)
----0x7fff5bcc66d2 -> c(63)
----0x7fff5bcc66d1 -> b(62)
----0x7fff5bcc66d0 -> a(61)

var:s1
content:ghijklmnopqrstuvwxyz
----0x7fff5bcc66cb -> l(6c)
----0x7fff5bcc66ca -> k(6b)
----0x7fff5bcc66c9 -> j(6a)
----0x7fff5bcc66c8 -> i(69)
----0x7fff5bcc66c7 -> h(68)
----0x7fff5bcc66c6 -> g(67)

var:s2
content:abcdefghijklmnopqrstuvwxyz
----0x7fff5bcc66c5 -> f(66)
----0x7fff5bcc66c4 -> e(65)
----0x7fff5bcc66c3 -> d(64)
----0x7fff5bcc66c2 -> c(63)
----0x7fff5bcc66c1 -> b(62)
----0x7fff5bcc66c0 -> a(61)

var:s3
content:qrstuvwxyz
----0x7fff5bcc66ea -> (00)
----0x7fff5bcc66e9 -> z(7a)
----0x7fff5bcc66e8 -> y(79)
----0x7fff5bcc66e7 -> x(78)
----0x7fff5bcc66e6 -> w(77)
----0x7fff5bcc66e5 -> v(76)
----0x7fff5bcc66e4 -> u(75)
----0x7fff5bcc66e3 -> t(74)
----0x7fff5bcc66e2 -> s(73)
----0x7fff5bcc66e1 -> r(72)
----0x7fff5bcc66e0 -> q(71)
----0x7fff5bcc66df -> p(70)
----0x7fff5bcc66de -> o(6f)
----0x7fff5bcc66dd -> n(6e)
----0x7fff5bcc66dc -> m(6d)
----0x7fff5bcc66db -> l(6c)
----0x7fff5bcc66da -> (00)
----0x7fff5bcc66d9 -> z(7a)
----0x7fff5bcc66d8 -> y(79)
----0x7fff5bcc66d7 -> x(78)
----0x7fff5bcc66d6 -> w(77)
----0x7fff5bcc66d5 -> v(76)
----0x7fff5bcc66d4 -> u(75)
----0x7fff5bcc66d3 -> t(74)
----0x7fff5bcc66d2 -> s(73)
----0x7fff5bcc66d1 -> r(72)
----0x7fff5bcc66d0 -> q(71)

Obviously, sscanf has overflow so data filled in s1 and s3 wrongly.

Check the memory address for s1,s2,s3, it seems OS assign it as below:

s3 [0x...de,0x...ea]
...garbage data here
s1 [0x...c6,0x...cb]
s2 [0x...c0,0x...c5]

But I define it as s1 then s2 then s3, why not it assign memory as:

s1 [0x...c6,0x...cb]
s2 [0x...c0,0x...c5]
s3 [0x...a5,0x...bf]

Questions:

  1. Why s3 assigned address above s1?
  2. Why some data inserted between s3 and s1?
beetlej
  • 1,841
  • 4
  • 13
  • 27
  • [This old answer of mine](http://stackoverflow.com/a/38202469/440558) and [this blog-post of mine](https://ghost.pileborg.se/2016/08/28/the-difference-between-arrays-decaying-to-pointers-and-pointers-to-arrays/) should contain all you need to know about arrays and pointers to them. The important thing to know is that `p` is wrong (wrong type) and `q` is *very* wrong (as it points out of bounds). – Some programmer dude Feb 10 '17 at 20:56
  • Also, when you do `sscanf` to write into `s2` you write out of bounds. That leads to *undefined behavior*. And once you have UB then your whole program is unreliable and there's really nothing more to say. – Some programmer dude Feb 10 '17 at 20:58
  • The layout of local variables in a function is at the whim of the compiler — there could be any reason for its choice of layout, or no reason. It shouldn't matter to you; you can't do anything portable if you're depending on a particular memory layout for the different variables. Within a compound variable like an array or a structure (or an array of structures), there are rules — and considerable flexibility too. But there aren't many rules for local variables in a function, beyond separate variables must have separate storage if their lifetimes overlap. – Jonathan Leffler Feb 10 '17 at 21:45

0 Answers0