This question already has answers here:
Consistent pattern in garbage value from uninitialized array
(1 answer)
Is there a way to predict the value of an uninitialized variable?
(1 answer)
Why local variables have undetermined values in C if not initialized?
(2 answers)
Where do the values of uninitialized variables come from, in practice on real CPUs?
(4 answers)
Closed last month.
This post was edited and submitted for review last month and failed to reopen the post:
Original close reason(s) were not resolved
I know that uninitialized variables don't have a particular set value, but I want to know how these uninitialized values are actually decided, either by the compiler or at runtime.
I find that if i run the below code, different outputs will occur:
#include <stdio.h>
int main() {
int *ptr;
printf("%p\n", ptr);
return 0;
}
Output: (clang)
$ clang a.c -o a; ./a
0x7fffed5e33c0
$ clang a.c -o a; ./a
0x7ffe81aa8660
...
Output: (gcc)
$ gcc a.c -o a; ./a
(nil)
How exactly are uninitialized values decided?
They are not decided. That's the very point.
So an optimizing compiler might even optimize out reading the value from memory if it knows it is undefined. Or assume it is something convenient. Or release nasal daemons.
So if you want to know what happens, you need to look at the generated machine code, and possibly run the code in disassembly mode under debugger if value used by assembly code is only known at runtime.
Related
This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed last year.
#include<stdio.h>
int main(){
int *i;
*i=1;
int a[5]={10,20,30,40,50};
printf("%d\n",&a[4]);
printf("%d\n",&a[3]);
printf("%d\n",&a[2]);
printf("%d\n",&a[1]);
printf("%d\n",&a[0]);
printf("%d\n",i);
return 0;
}
printf("%d\n",i); This print statement prints different values every time it is ran, which is understandable as the program is loading on RAM(am I right?).
But,
Then why does printf("%d\n",&a[0]);(or any other a[i]) prints the same value each time the program is run, does that mean the program is saving the array on harddisk, if so why?
Please answer
Please do share this question if you want the answer
printf("%d\n",i); This print statement prints different values every time it is ran, which is understandable as the program is loading on RAM(am I right?).
No, you're not actually initialising i so its value is random garbage: if you compile using address sanitizer (-fsanitize=address), the program will immediately explode when reaching *i = 1, and compiling with -Wuninitialized will also point to this issue.
But there's no requirement that i is stable either, when properly initialised: it depends how the allocator in use works, and where it decides to put the value in the heap.
Then why does printf("%d\n",&a[0]); (or any other a[i]) prints the same value each time the program is run, does that mean the program is saving the array on harddisk, if so why?
That's just a peculiarity of your machine, it doesn't occur on my system (that is the addres of a moves around): it depends where the runtime decides to put the stack and what it decides to do (or not) before running main (even more so if you enable stack ASLR), since a lives on the stack.
FWIW on my system, using clang, i always has the same value (when properly initialised using int *i = malloc(sizeof *i);, but the value of a moves around.
*i points to a random address anywhere
The array a[] is on stack whose (start) address may be the same each time
#include<stdio.h>
int main(){
int *i;
int a[5]={10,20,30,40,50};
//%p denotes we are printing address that a pointer points to
printf("%p\n",&a[4]);
printf("%p\n",&a[3]);
printf("%p\n",&a[2]);
printf("%p\n",&a[1]);
printf("%p\n",&a[0]);
*i=1;
printf("%p\n",i);
return 0;
}
$gcc memory_address.c && ./a.out
0x7ffe282734d0
0x7ffe282734cc
0x7ffe282734c8
0x7ffe282734c4
0x7ffe282734c0
Segmentation fault (core dumped)
$ gcc memory_address.c && ./a.out
0x7fffb1b8b670
0x7fffb1b8b66c
0x7fffb1b8b668
0x7fffb1b8b664
0x7fffb1b8b660
Segmentation fault (core dumped)
We are getting Segmentation fault because i pointer is not assigned a valid reference and array a is assigned new memory on ram every time you run your program.
This question already has answers here:
(Why) is using an uninitialized variable undefined behavior?
(7 answers)
Closed 3 years ago.
if i run this program:
#include <stdio.h>
int main()
{
int a=32,b=2,c,i;
for(i=0;i<3;i++){
printf("%d\n",c);
c=a/b;
a=c;
}
return 0;
}
the output is:
32765
16
8
In there, I dont define the value of C, Where from came this output 32765.?
even again i run this code more time,it show different values like 32764,32767. Why this different output showing on?
Because c has automatic storage duration (i.e. is a non-static local variable) and is uninitialized, its value is indeterminate. Attempting to print an uninitialized variable that never had its address taken (i.e. was not the subject of the address-of operator &) invokes undefined behavior.
Even if you did take the address of c you could still have undefined behavior if it contains a trap representation. If it does not contain a trap representation (and most implementations don't have them), the the value is unspecified which simply means the printed value can't be predicted.
Automatic variables (a local variables which are allocated and deallocated automatically when program flow enters and leaves the variables's scope) for which there is no explicit initializer have undefined (i.e. garbage) values.
This question already has answers here:
pointer default value .?
(4 answers)
Closed 4 years ago.
How are pointers in C initialized? It seems like previous declarations change how they are initialized.
Consider the following example:
int *a;
printf("a: %p\n", (void*)a);
This code snippet results in
a: (nil)
So one could think that variables at function start are initialized with null, but if I execute this code:
int *a;
for(int i = 0; i < 1; i++){
int *b;
printf("a: %p\n", (void*)a);
printf("b: %p", (void*)b);
}
This is the result:
a: 0x7ffff3bb2e40
b: (nil)
How can I determine how the variables are initialized?
If a pointer is defined at file scope, it is initialized to NULL.
If it is defined at block scope, the pointer is uninitialized, so it could have any random value, including NULL.
Given that you are not assigning an initial value, it depends on what there is on the memory beforehand. So there are two possibilities
Garbage. Indeterminate values which come from a previous execution or status, etc...this l yields an undefined behaviour.
Initialization during startup. It is quite common to initialize to zero some segments of memory such us the bss segment during the startup (before main()). In this case, you are not initializating the variable, you are initializating the bunch of memory in which the variable is allocated, anyway, this won't yield an undefined behaviour.
Edited for accuracy due to M.M 's comment.
How are pointers in C initialized?
In C, local pointers (in automatic variables) are not initialized unless you code explicitly their initialization. You have an undefined behavior. Be scared.
The only pointers which are implicitly initialized are those in global or static variables (so called file scope variables). In practice, such pointers are initialized to all zero bits, which usually means the NULL pointer.
In practice, with a modern compiler like a recent GCC, you should enable all warnings and debug info (e.g. compile with gcc -Wall -Wextra -g). Then you'll get warnings. Improve your code to have none.
This question already has answers here:
Does "Undefined Behavior" really permit *anything* to happen? [duplicate]
(9 answers)
Closed 6 years ago.
I have one incredible segment crash call stack in C, could anyone help me out?
int function(struct A *a)
{
... some other declare
struct B *b = a->b;
int count, len;
... some other declare
struct C *c = b->c; /* not crash here */
....some other decalre
if (b->e) { /*crash log indicate b is NULL and crash here,first line instrucment code*/
.....
}
....
}
My question is why the crash did not happened at the struct C *c = b->c.
GCC is the compiler.
Tony
The compiler does not guarantee ordered execution of instructions unless there is a data flow dependency. It has numerous optimizations, one of which is data flow optimization.
Also, if you don't use the variable c at all, the compiler will optimize it out of the code (dead code optimization) and you may not see a crash at all (if the rest of the program works fine).
One easy way to understand which optimization is happening is to access the c variable somewhere. Another way is to disable optimizations (-O0 in GCC).
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
Ubuntu 10.04, C, gcc, x86 Intel proc:
When trying to print the address of an environmental variable using printf, the address printed is not correct in this toy program (this is a consciously backward version in which I tried to isolate the source of the problem by saving the address value on the heap, not using a pointer directly as I read it can be overwritten, and using a pointer straight up produced the same issue):
#include <stdio.h>
#include <stdlib.h>
int main(){
const char* d = getenv("TEST");
unsigned i = (unsigned*) malloc(sizeof(unsigned));
i = (unsigned*) d;
printf("%s at location 0x%8d.\n", "TEST", i);
}
EDIT: same issue with this (the original) version)
int main(){
const char* d = getenv("TEST");
printf("%s at location %p.\n", "TEST", d);
return 0;
}
This question has nothing to do with how to print a pointer. Kindly read on.
If I change the program to not print TEST's address, but TEST as a string (its value), no problem.
However, the address returned is not the address at which the environmental variable is actually located before entering the print sub-routine; and which, by the above set-up, should be printed. Using main's disassembly and TEST's address in the eax register, I am referred to the proper location of the TEST variable, which is a little further down than main's stack frame at about 0xbffffiii on my system (i any hex value). The address value printed is on the order of 0xbfeiiiii.
I don't understand. Is this a security precaution to prevent environmental variables from being overwritten (eg, to smash the stack)? If yes, does the compiler really keep track of transferring the address as I do above, and silently adjusting its value?
Or am I missing something? (probably)
Many thanks.
P.S.: To remove imaginable sources of issues, I compiled first with no options, then:
gcc -O0 -static -fno-stack-protector -g program.c
This is not the right way to print an address. Just use the %p format to print (void*)d.
printf("%s at location 0x%p.\n", "TEST", (void*)d);
I figured it out, following a comment by R.. further above who pointed me in the direction of ASLR.
I was unfamiliar with ASLR stack protection. What I describe is due to ASLR scrambling the memory address space to prevent prediction of the location of variables relative to it. ASLR has long been default switched on in LINUX kernels it appears.
To see what I meant, get su privileges, then enter (the precise integer to send might vary based on your distro; on mine it is 0, and the default 2. Also better confirm the file only contains 1 integer by first looking at it, as it does on my system):
cd /proc/sys/kernel
export OLD=$(less randomize_va_space) // save old value to restore after
echo 0 > randomize_va_space // 0 == turn off ASLR
Then run my little program again: it will report back the address I expected (around 0xbffffiii). After, obviously, restore old protection using
echo $OLD > randomize_va_space
Many thanks for everyone who spend some of their time trying to help.
Storing a char* pointer in an unsigned variable might work on some systems, but is not portable. For example, on my 64-bit Ubuntu box sizeof(char*)==8 and sizeof(unsigned)==4. The portable way to store a pointer in an integer variable is to use the intptr_t type.
Alternatively, to simply print the address use %p like so:
#include <stdio.h>
#include <stdlib.h>
int main() {
const char* d = getenv("TEST");
printf("%s at location %p.\n", "TEST", d);
}
On my Ubuntu box, this prints out either
TEST at location (nil).
or
TEST at location 0x7fff8cf34628.
depending on whether $TEST is set (of couse the address can vary).
However, the address returned is not the address at which the
environmental variable is actually located before entering the print
sub-routine; and which, by the above set-up, should be printed. Using
main's disassembly and TEST's address in the eax register, I am
referred to the proper location of the TEST variable, which is a
little further down than main's stack frame at about 0xbffffiii on my
system (i any hex value). The address value printed is on the order of
0xbfeiiiii.
Note that there are several copies being made here: the literal "TEST" in your program, used to find the key "TEST" in the environment of your program, the value string for the key "TEST" in that environment and a pointer to that value string returned by getenv(). I don't know what you expected to get, but the environment is generally not near the stack in any of the x86 environments I know.
What you probably saw in the disassembly was the pointer to the "TEST" string in your program, somewhere in the local stackframe for main(). That is not the environment variable, that is a string used to search for the environment variable in the environment, by comparing the string in your program with the real one.
So I don't really know what you expected, but it looks as if you are expecting the wrong thing, sorry.
The address of the literal "TEST" should be somewhere in your program, probably in a read-only segment. The address of the pointer to that string is somewhere close to the stack pointer. The address of the string "TEST" in your environment should not be near the stack at all (probably at a lower address than your program). The string associated with "TEST" should be very near to it, and that should be the address returned by getenv().
You are assuming that environment variables are stored in some particular place, apparently based on examining memory with gdb. I suggest that it's not your program's output that's incorrect, but your assumptions about where environment variables are stored.
getenv() returns a pointer to a string which hold the value of the specified environment variable. If it's at a different address than what you expected, how is that a problem?
Consider the following program:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char *test = getenv("TEST");
if (test == NULL) {
puts("test == NULL");
}
else {
printf("test == %p, points to \"%s\"\n", (void*)test, test);
/* WARNING: The following has undefined behavior! */
*(char*)test = 'X';
system("echo $TEST");
}
return 0;
}
When I run it on my system (Ubuntu 11.04, x86, gcc 4.3.4) with $TEST set to "foobar", it prints:
test == 0x6125f299, points to "foobar"
Xoobar
So getenv() gave me a pointer to a string that, when I modified it, showed up as a change in the environment of a child process.
Again, what exactly is the problem?