-2

I have a simple code:

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

int main(void){
  char *str = (char *) malloc(4*sizeof(char));
  int i;
  for(i = 0; i < 64; i ++)
    printf("%d, %ld, %d, %c\n", i, (long) &(str[i]), (int) str[i], str[i]);
  return 0;
}

I allocate a memory into str using malloc() which is available to save 4 letters in str[0], ..., str[3]. I know that malloc() does not initialize its memory while calloc() does.

This program prints str[i] with i, address of str[i], value of str[i], letter of str[i], in order. (I use 64-bits Ubuntu, hence address is long type.)

As expected, addresses are quite different for every time I run the program. But I wonder that why str[24], str[25], and str[26] are -31, 15, 2, repectively, and other values are all 0 as you can see below:

Ubuntu 12.04.5

(Note that without option -O0 gives same result.)

How can memory has same sequence (0,0,...,0,-31,15,2,0,0,...) even though only first four 0s in that sequence are allocated and others are out of care?

Analysis
  • 240
  • 1
  • 11
  • 1
    You do understand that `str[24:26]` and `str[4:63]` are well outside the range that you allocated right? And therefore you are exhibiting undefined behavior? – Bill Lynch Apr 19 '15 at 16:34
  • @BillLynch Of course I know. But whenever I run the program, str[24:26] has -31, 15, 2 always. I think this phenomenon is very abnormal because these str[24:26] is outside the range as you pointed. – Analysis Apr 19 '15 at 16:36
  • `malloc` may well get more memory from the OS than you actually asked for, for its own efficiency. You haven't initialised the memory you are looking at, so it might contain anything. – Weather Vane Apr 19 '15 at 16:41
  • I suspect that you're seeing a header for another piece of memory that malloc() allocated earlier. Perhaps before `main()`. – Bill Lynch Apr 19 '15 at 16:42

1 Answers1

0

As you just have pointed out, malloc() doesn't initialize memory (by the way, even if it would, starting from str[4*sizeof(char)] it wouldn't be initialized because it's already out of range).

This means that you print out data that was at this memory location before. It's undefined behaviour so strictly unpredictable.

The fact that you see the same value, could be a coincidence. But if repeatable, and always with the same values, it most probably traces of the what the OS and the standard library did to initialize the environment of your process before giving control to your main().

There is a related SO question about uninitialized variables on stack. The principle of unitialized data giving access to remanent value is similar here, only that it's on the heap.

Here an experiment : a small programme to try to show you the kind of thing that could happen (attention: it's implementation dependent):

int main() {
    int i; 
                                  // first part ================
    char *p=(char*)malloc(100);   // allocate a region in memory
    for (i=0; i<100; i++)         // initialize it to 0 
        p[i]=0; 
    strcpy (p+10, "Christophe");  // put some value womewhere in the middle
    free(p);                      // release memory 

                                  // second part ============
    char *q= (char*)malloc(100);  // innocently allocate new memory
                                  // and display its content
    printf ("%ld==%ld ? %c%c%c\n", (long) p, (long)q, q[10],q[11], q[12]); 

    return 0;
}

So you could imagine that something like the first part of this code could be run during the initialization sequence of the standard library (could be at startup of the programme, or the first time you call malloc()).

Here a live demo of this code.

Community
  • 1
  • 1
Christophe
  • 68,716
  • 7
  • 72
  • 138
  • But every time, addresses are changed. As you can see in the picture, `str` is 7598096, thus -31 is stored at 7598120. I re-run the program just before now, `str` is 25088016 and -31 is stored at 25088040. If OS gives same memory block everytime, then why these have different addresses? – Analysis Apr 19 '15 at 16:51
  • @Analysis Yes: the initializaton sequence is run in the address space of your process. So if it leaves traces of its activity in memory, their place will probably be at compared to the start the start of the process address space. – Christophe Apr 19 '15 at 16:58
  • @Analysis: I've edited to add some code to try to show you the phenomenon. – Christophe Apr 19 '15 at 17:18