Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I change a local const variable through pointer casts but not a global one in C?

I wanted to change value of a constant by using pointers.

Consider the following code

int main()
{
    const int const_val = 10;
    int *ptr_to_const = &const_val;

    printf("Value of constant is %d",const_val);
    *ptr_to_const = 20;
    printf("Value of constant is %d",const_val);
    return 0;
}

As expected the value of constant is modified.

but when I tried the same code with a global constant, I am getting following run time error. The Windows crash reporter is opening. The executable is halting after printing the first printf statement in this statement "*ptr_to_const = 20;"

Consider the following code

const int const_val = 10;
int main()
{
    int *ptr_to_const = &const_val;
    printf("Value of constant is %d",const_val);
    *ptr_to_const = 20;
    printf("Value of constant is %d",const_val);
    return 0;
}

This program is compiled in mingw environment with codeblocks IDE.

Can anyone explain what is going on?

like image 808
udpsunil Avatar asked Jun 03 '09 16:06

udpsunil


3 Answers

It's a constant and you are using some tricks to change it anyway, so undefined behavior results. The global constant is probably in read-only memory and therefore cannot be modified. When you try to do that you get a runtime error.

The constant local variable is created on the stack, which can be modified. So you get away with changing the constant in this case, but it might still lead to strange things. For example the compiler could have used the value of the constant in various places instead of the constant itself, so that "changing the constant" doesn't show any effect in these places.

like image 145
sth Avatar answered Oct 18 '22 14:10

sth


It's in read only memory!

Basically, your computer resolves virtual to physical addresses using a two level page table system. Along with that grand data structure comes a special bit representing whether or not a page is readable. This is helpful, because user processes probably shouldn't be over writing their own assembly (although self-modifying code is kind of cool). Of course, they probably also shouldn't be over writing their own constant variables.

You can't put a "const" function-level variable into read only memory, because it lives in the stack, where it MUST be on a read-write page. However, the compiler/linker sees your const, and does you a favor by putting it in read only memory (it's constant). Obviously, overwriting that will cause all kinds of unhappiness for the kernel who will take out that anger on the process by terminating it.

like image 21
Alex Gartrell Avatar answered Oct 18 '22 14:10

Alex Gartrell


Casting away pointer const-ness in C and C++ is only safe if you are certain that the pointed-to variable was originally non-const (and you just happen to have a const pointer to it). Otherwise, it is undefined, and depending on your compiler, the phase of the moon, etc, the first example could very well fail as well.

like image 21
Tyler McHenry Avatar answered Oct 18 '22 12:10

Tyler McHenry