What should be clarified in this short article is how in C language, const ensures that variables are not modified?
We can think of two ways:
The first is to prevent statements that modify const variables from being modified by the compiler, so that such programs cannot be compiled;
The second type is blocked by the operating system, that is, the memory address access permission of const is marked as "read-only". Once the running program tries to modify it, an exception will be generated and the process will be terminated.
Both methods thought of above can achieve the purpose of not modifying the value of a certain variable. So which one is it? Let’s write two examples to take a look.
Let’s first look at a simple example, source file:
#include <> const int a=10; int main() { int *p=&a; printf("initial: %d\n",a); *p=1; printf("modified: %d\n",a); return 0; }
Compile and you will receive a warning:
$ gcc -o const1
: In function ‘main':
:7:12: warning: initialization discards ‘const' qualifier from pointer target type [-Wdiscarded-qualifiers]
int *p=&a;
Ignore it, run the program:
$ ./const1
initial: 10
Segmentation fault (core dumped)
There was an error in running, and the error was reported as "segmentation fault", that is, "segmentation fault". It reminds us that the program uses the wrong permissions to access a certain area of the memory. This shows that the operating system loads the variable $a$ into a read-only memory area, so the write operation to the address of the area will raise an exception, which is determined by the memory protection mechanism of the operating system.
That is to say, in this program, the read-only attribute of const is implemented by the operating system, not by the compiler (the compiler only throws warning and does not prevent compilation from passing).
Is this right? Not exactly right, let's look at another example, source file:
#include <> int main() { const int a=10; int *p=&a; printf("initial: %d\n",a); *p=1; printf("modified: %d\n",a); return 0; }
Compile or receive the same warning:
$ gcc -o const2
: In function ‘main':
:6:12: warning: initialization discards ‘const' qualifier from pointer target type [-Wdiscarded-qualifiers]
int *p=&a;
Ignore it, run the program:
./const2
initial: 10
modified: 1
Huh? How did it run successfully, and the value of a has been successfully modified?
Based on the above two examples, we can draw the following inference:
const is just a modifier for variables in C language. In the example, a is more like a "variable that is not intended to be modified". It is just a syntactic declaration, and its function is to tell the compiler "I don't want to modify it", so the compiler will syntacically check whether there are statements in the program that modify it (for example, "a=1;"). Once you find such a statement that "violates the original intention", it will report an error to prevent you.
However, what the compiler prevents is only the modification of the corresponding value of the symbol a, but does not prevent the modification of the value of this address. The reason why the source file "" can be compiled smoothly and runs normally is because it uses a pointer named a to point to it, thus bypassing the compiler's syntax check.
For example, Zhou Shuren's pen name is Lu Xun. The police only know that they want to arrest Lu Xun. At this time, he can deceive them with the sentence "What does it have to do with you arresting Lu Xun?"
From this perspective, the function of const is achieved by the compiler only from syntax checks, so there are runtime vulnerabilities.
So why can't "" work normally?
If you look at these two source programs carefully, the only difference is that in "", a is declared as a global variable, while in "", it is declared as a local variable in the main function. The difference between global variables and local variables is that the former will be loaded before the program starts running, and will remain in memory after loading, and the loaded position is in the data area until the program exits; the latter will be loaded only when it is run, and the loaded position is the runtime stack frame, which will be recycled once it exceeds the effect.
Therefore, the compiler will optimize the const int a declared as a global variable and put it in the read-only memory area. The permissions in this memory area are "read\ only". The permission information is saved by the segment table maintained by the operating system. Every time the program accesses a certain address, the operating system will check whether its access permissions are legal. "" attempts to access the "read-only" segment in "" to use "write" method, and will naturally report the "segment fault".
From this perspective, when a is a global variable, the compiler optimizes the originally "variable that is not intended to be modified" into a "real constant" and then hand it over to the operating system to maintain its unchanged properties.
To sum up, C's original intention is to let the compiler ensure the unchanged attribute of $const$. This attribute has loopholes (you can use pointers to trick the compiler into modifying it). Therefore, when the object modified by const is a global variable (global variables are very important because many source files need to access it, which affects the whole body, so it should not be changed easily), the compiler knows that its ability is limited and can only manage the compilation and the runtime cannot be controlled, so it optimizes the statement to program the real constants, so the operating system's memory protection function performs this responsibility.
This optimization is not stipulated by C, but a choice made by the compiler manufacturer for practical application considerations.
The above is my speculation based on the behavior of the compiler and program when running. This idea is not appropriate. It is just that I encountered confusion in the above two examples while programming, and I did not find the information that was explained very clearly, so I wrote it out. If you want to further verify, you should check the compiled executable file segmentation situation. I was lazy and didn't read it, so I put it here for the time being.
If the speculation is incorrect, I hope a senior will point it out.
Summarize
This is the article about how to ensure that const variables are not modified in C language. For more related contents of const variables in C language, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!