-6

I am simply testing what would be the output if I try to dereference a pointer, which points to out of range of dynamically created memory using calloc() and expecting memory fault or some garbage value instead. It is giving 0 as output, which is basic feature of calloc() that it intializes allocated memory with '0', or is it just due to undefined behavior?

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

int main()
{
    int *p = NULL;
    p = (int *)calloc(10, 8);
    if(p != NULL)
    {
        printf("\n successfully allocated memory ");
    } 
    else
        EXIT_FAILURE;
    printf("\n Thirty first element of memory is %d \n",p[30]);
}

Result :

successfully allocated memory
Thirty first element of memory is 0
nalzok
  • 14,965
  • 21
  • 72
  • 139
theartist33
  • 470
  • 1
  • 6
  • 13

4 Answers4

1

From a language perspective, accessing out of bounds memory is undefined behavior, meaning that anything can happen.

One possible explanation for that particular behavior is that most operating systems will zero out any memory before they give it to your process, independently of what function you where using internally (this is a security measure, so you can't read data that was used by other processes).

To get garbage data, you usually have to have used and freed the same memory before inside your program (in which case it retains its old value). Or of course, if your index is so far off that you are indexing into a neighboring data structure.

The reason your program didn't just crash is that malloc (and similar functions) usually request much more memory from the os, than what you are requiring and use the surplus memory the next time you call malloc. So from the OS perspective you are accessing valid memory, and there is no reason to terminate your program.

MikeMB
  • 20,029
  • 9
  • 57
  • 102
  • Upvoting for the only attempt to analyze the question, rather than cave in to 'undefined behavior' mantra. – SergeyA Mar 29 '16 at 14:01
  • @SergeyA: Thanks. I sometimes wonder why people want to use a low-level programming language like c++, but then mark thinking of things beyond the abstract machine described in the standard as heresy. – MikeMB Mar 29 '16 at 14:17
  • I think, because they are tought this way, and do not realize what they are dealing with. – SergeyA Mar 29 '16 at 14:23
1

You are trying to access p + 30 * sizeof(int) which is p + 120 while you have allocated only 8 * 10 = 80 bytes, so max address you can access is p[19]

LibertyPaul
  • 1,139
  • 8
  • 26
0

Accessing out of range memory is Undefined Behaviour. Hence the value which you get can be 0 or 1 or Batman


The point is, you cannot ask any explanation or reason for things that are undefined. Anything can happen in such a scenario.

Also, you would get a seg fault if you try to access a memory location which your program is not allowed to access. That may not be the case always when you access out of bounds memory. It can lie well inside the user memory area of the program.

Haris
  • 12,120
  • 6
  • 43
  • 70
  • so shall I take it as undefined Behavior ? – theartist33 Mar 29 '16 at 13:56
  • @theartist33, It is undefined behavior. You cannot look for an explanation for this. – Haris Mar 29 '16 at 13:57
  • @Haris, I disagree. Understanding undefined behavior is invaluable when you need to troubleshoot an application. It just works in reverse. – SergeyA Mar 29 '16 at 14:00
  • @SergeyA, Understanding undefined behavior as in why such an out put is coming? Or why it is undefined behavior? – Haris Mar 29 '16 at 14:01
  • @Haris, both, and equally important. – SergeyA Mar 29 '16 at 14:02
  • @SergeyA, I would agree to your logic if you can show a standard explaining undefined behavior for certain outputs. On the other hand, why is it undefined behavior is a valid question and is important in C perspective. – Haris Mar 29 '16 at 14:04
  • @Haris, it is not about standard. It is about real life. For example, why an application which was running fine in production for 3 years, suddenly crashing after a commit in a very different place? Understanding how undefined behavior manifests itself in your system is extremely valuable tool for any real life developer. – SergeyA Mar 29 '16 at 14:11
  • @SergeyA, Yes. That is important. One has to know when can undefined behaviour occur, or which construct would lead to an undefined behaviour. How would you justify the output, if there is no standard rule written for it in the very standard that the whole (C) environment is following. – Haris Mar 29 '16 at 14:15
  • @Haris, like I said - you justify the output by knowing your system, your compiler and your CPU. This is what actually differentiates the scholar from the software developer. – SergeyA Mar 29 '16 at 14:21
  • @SergeyA, I am very much open on a discussion on why things like that output can happen. But what I don't agree with is justifying the output by a logic out of those discussions. You say by knowing your system, compiler and CPU. A Compiler would implement only what is in the standard, rest is left on the system. Now that particular memory could have been holding that particular data for any reason. – Haris Mar 29 '16 at 14:26
  • @Harris, compiler will generate a certain code. A code will perform a certain actions. Those actions will produce a certain result. And if you are a good developer, you should be able to understand the result and trace it back to the code. One way of doing is by knowing your undefined behavior. – SergeyA Mar 29 '16 at 14:28
0

I think windows zeroes a freed page before making available for allocation. Have fun with the code below.

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

int g = 0;
unsigned long long* p=NULL;

void signal_handler(int ssc)
{
    printf("Error %d \n", ssc);
    printf("segfault after %llu bytes",g*8);
    printf("should i go backwards? press enter");
    getch();
    g=0;
    do
    {
        printf("Virtual Adress:%llu is %llu\n",p+g,*(p+g) );
        Sleep(1);
        g--;    
    }
    while(1);
}



int main ()
{

if(SIG_ERR == signal(SIGSEGV, signal_handler) ) {printf("error seting signal handler %d\n",SIGSEGV);}




p = (unsigned long long*)calloc(10,8);

if( p!= NULL)
{
    printf("successfully allocated memory\n");
}
else
{
    EXIT_FAILURE;
}



    do
    {
        printf("Virtual Adress:%llu is %llu\n",p+g,*(p+g) );
        Sleep(2);
        g++;    
    }
    while(1);


    return 0;
}