Location of a dereferenced uninitialized pointer in memory? - c

I have this code example in c from an introductory Embedded system course quiz :
#include <stdlib.h>
#include <stdint.h>
//cross-compiled for MSP432 with cortex-m0plus
int main() {
int * l2;
return 0;
}
I want to know the memory segment ,sub-segment, permissions and lifetime of *l2 in memory.
What I understand is that the pointer l2 is going to be allocated in the stack sub-segment first then because it's uninitialized it's going to get a garbage value which is in this case any value it finds in the stack; I assumed it was in the .text or .const with a static lifetime and none of these answers were right, so am I missing something here ?
Edit:
After I passed the quiz without solving this point correctly, the solution table says it's in the heap with indefinite lifetime. what i got from this answer is that : because a pointer itself is stored in stack and the object it points to is uninitialized (it's not auto or static), it's stored in the heap.. I guess ??

It depends on the implementation.
Usually as it is local automatic variable it will be located on the stack. Its lifetime is the same as lifetime of the main function. It can be only accessed from the main function.
But in real life as you do not do anything with it, it will be just removed by the compiler as not needed even if if you compile it with no optimizations https://godbolt.org/z/1Y6W5j . In this case its location is "nowhere"
Objects can be also kept in the registers and not be placed in the memory https://godbolt.org/z/8nWxxz
Most modern C implementations place code in the .text segment, initialized static storage location variables in the .data segment, not initialized static storage location variables in the .bss segment and read only data in the .rodata segment . You may have plenty other memory segments in your program - but there are so many options. You can also have your own segments and place objects there.
Stack and heap location are 100% implementation defined.

The value stored in l2 is indeterminate - it can even be a trap representation. The l2 object itself has auto storage duration and its lifetime is limited to the lifetime of the enclosing function. What that translates into in terms of memory segment depends on the specific implementation.
You can’t say anything about the value of *l2, unless your specific implementation documents exactly how uninitialized pointers are handled.

Related

When/where are local arrays allocated?

https://www.gnu.org/software/libc/manual/html_node/Memory-Allocation-and-C.html describes automatic allocation of local variables. I understand that local variables are commonly allocated on the stack. I can imagine how an int might be allocated on the stack; just push its value. But how might an array be allocated?
For example, if you declare an array char str[10];, does that 10 bytes of space go on the stack, or is it allocated somewhere else, and only the str pointer is pushed to the stack? If the latter, where is the 10 bytes of space allocated?
Furthermore, when exactly are local variables, including arrays, allocated? I commonly see heap allocation referred to as "dynamic allocation", implying that automatic variables are not dynamically allocated. But automatic variables may be declared within flow-of-control constructs and function bodies, so the compiler can't possibly know before runtime exactly how much space will be occupied by automatic variables. So automatic variables must also be dynamically allocated, right?
Edit: I would like to emphasize the first half of this question. I am most interested in understanding when and where the space for local arrays is allocated. On the stack? Somewhere else?
Edit 2: I made a mistake when I originally included the C++ tag for this question. I meant to ask only about the C language and its implementations. I apologize for any confusion.
In the C 2018 standard, clause 6.2.4, paragraphs 6 and 7 tell us about the lifetimes of objects with automatic storage duration. Paragraph 6 covers such objects that are not variable length arrays:
… its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way. (Entering an enclosed block or calling a function suspends, but does not end, execution of the current block.) If the block is entered recursively, a new instance of the object is created each time.
Thus, if we have this code:
{
PointA;
int x = 3;
PointB;
}
then x exists in the C model as soon as execution reaches PointA—its block was entered, and that is when the lifetime of x begins. However, although x already exists at PointA, its value is indeterminate. The initialization only occurs when the definition is reached.
Paragraph 7 tells us about variable length arrays:
… its lifetime extends from the declaration of the object until execution of the program leaves the scope of the declaration.
So, if we have this code:
{
PointA;
int x[n]; // n is some variable.
PointB;
}
then x does not exist at PointA. Its lifetime begins when int x[n]; is reached.
Keep in mind this existence is only in terms of C’s abstract model of computing. Compilers are allowed to optimize code as long as the observable results (such as output of the program) are the same. So the actual code generated by a compiler might not create x when the block is entered. (It might not create x at all; it could be optimized away completely.)
For example, if you declare an array char str[10];, does that 10 bytes of space go on the stack, or is it allocated somewhere else, and only the str pointer is pushed to the stack? If the latter, where is the 10 bytes of space allocated?
In general, the array's storage is allocated on the stack, just like any other local variable. This is compiler and target-specific. Even on a x86_64 machine, a 4 billion byte array is probably not allocated on the stack. I'd expect one of: a compile error, a link error, a runtime error, or it works somehow. In the last alternative, it might call new[] or malloc() and leave the pointer to the array on the stack in place of the array.
Notice that the array's allocation and its pointer are the same thing, so your addition of allocated somewhere else, and only the str pointer wording might indicate confusion. The allocation occurs and the name for it are not independent data.
What you ask for is depends on the language implementation (the compiler). To answer your question, this is (a simplified overview of) what compilers usually do for compiled languages (like C/C++):
When the compiler finishes parsing a function, it keeps a symbol table of all local variables declared in this function, even those declared "syntactically" during the instruction flow of the function (like local loops variables). Later, when it needs to generate the final (assembly) code, it generates the necessary instructions to push (or just moves the stack pointer) a sufficient space for all local variables. So, local loop variables, for instance, are not allocated when the loop starts execution. Rather, they are allocated at the beginning of the execution of the function containing the loop. The compiler also adds instructions to remove this allocated stack space before returning from the function.
So, automatic variables, like your char array, is totally allocated on the stack in this (common) scenario.
[EDIT] Variable length arrays (before C99)
The discussion above was for arrays having lengths known at compile time like this:
void f () {
char n[10];
....
}
If we stay in C language terms (before C99), variable-length arrays (arrays whose lengths are not known at compile-time, but rather at runtime) are declared as a pointer like this:
void f() {
char *n;
... //array is later allocated using some kind of memory allocation construct
}
This, in fact, just declares a pointer to the array. Pointers size is known to the compiler. So, as I said above, the compiler will be able to reserve the necessary storage for the pointer on the stack (just the pointer, not the real array) regardless of what will be the size of the array at runtime. When the execution reaches the line that allocates the array (using malloc, for instance), the array storage is dynamically allocated on the heap, and its address is stored in the local automatic variable n. In languages without garbage collection, this requires freeing (deallocating) the reserved storage from the heap manually (i.e. the programmer should add an instruction to do it in the program when the array is no longer needed). This is not necessary for constant-sized array (that are allocated on the stack) because the compiler removes the stack frame before returning from the function, as I said earlier.
[EDIT2]
C99 variable length arrays cannot be declared on the stack. The compiler must add some code to the resulting machine code that handles its dynamic creation and destruction at runtime.

difference between stack segment and uninitialized data segment

I was trying to get a hand over the memory allocation in c.
According to the following link, the stack and the uninitialized data segment are different and the uninitialized data of the local function goes to the uninitialized data segment.
If that is the case then what is stored in the stack segment in case of a code with uninitialized local variables? Is it empty?
I would not recommend reading "geeksforgeeks" tutorials. You have some misconceptions.
What they call "uninitialized data", the .bss segment, is in fact a store for variables of static storage duration that are zero-initialized. Including any such variable which is explicitly initialized to value zero.
An explanation of static storage duration and the different common segments, with examples, can be found here.
Only variables with static storage duration end up in .bss and .data. Local variables always end up on the stack, or in CPU registers, no matter if they are initialized or not.
(Please note that none of this is specified by the ISO C standard, but rather by industry de facto standards.)
the uninitialized data of the local function goes to the uninitialized data segment.
Well, that is not entirely true.
Read carefully, (from the same link, emphasis mine)
[...] uninitialized data starts at the end of the data segment and contains all global variables and static variables that are initialized to zero or do not have explicit initialization in source code. [...]
So, the automatic storage variables still resides in stack segment, irrespective of the fact whether they are initialized or not.
That said, a word of caution, this is "A typical memory representation", not universal. C standard does not mandate to have a stack segment (or any other), for the matter.

Physical memory location of uninitialised memory location in C program?

I have read that the uninitialized global variables in C will occupy the .bss section of the memory. Also it is just a place holder and doesn't occpy any space in object file.
My question is, once the uninitialised global variable is assigned with some value, where will it will get stored in physical memory?
For example:
int a[100];
int main()
{
a[10] = 25;
}
In the above program, where will the memory location be allocated?
Where the global variables will be stored is implementation defined, the C standard does not define where it should be saved.
The C Standard does not even mention Bss segment or Data segment it only defines the behavior such variables must show.
I think your misunderstanding is thinking that BSS is "permanently zero" memory. It's just a section of the program load mapping that's implicitly zero and thus avoids having any physical storage on disk, but otherwise it's a standard private writable mapping, and takes on physical existence as soon as it's written to.
If you're thinking about it moving, perhaps you're confusing virtual and physical addresses. The virtual address of an object in C never changes, and the physical address is never visible to you and should never matter.

Memory location of function argument

I'm preparing for my UNIX exam and there is a question about memory location of C variables.
Let's say we have code like this
char sth;
int some_function(int arg) {
int some_int;
// some code here
}
so I suppose that sth is located on the heap, some_int on the stack, but where is arg located?
Can somebody please explain how are C variables managed?
Thank you
Note that everything of this is implementation dependent. The C standard does not even utter the words stack, heap and so on. It just talks about the behavior that is expected from variables depending on their storage(static,extern,register etc).
Having said so usually arg will be located in the stack frame which is provided for the function. It's scope is limited to the function just as scope of some_int.
By the way sth is not on heap it has a static global storage.
Everything here is totally platform dependent and really not about C the language, but about How My Compiler Does It.
sth has static (global) storage, so its probably not on the heap, but rather in the global data segment. some_int is indeed in the local stack frame of some_function. The variable arg is populated within some_function, but where it lives is up to the compiler and what's usually known as the "calling convention": It may be allocated and cleaned up in the stack frame of the caller or the callee, and by the caller or the callee, depending on conventions, or passed in a register and not go into memory at all.
arg will be located in the stack (for desktop platforms at least).
Read a document called "smashing the stack for fun and profit" and you will understand how the memory is managed in C.
sth is in the static memory, arg and some_int are in the stack. arg is copied ("pushed") to the stack when some_function is called. The heap is dynamic memory and contains data allocated at the run time (using malloc for example).
Arguments are (with very few exceptions) passed on the stack.
You should be able to verify that they are in your computer architecture by just doing;
printf("%p - %p\n", &arg, &some_int);
They should normally be within a few bytes of each other.
Edit: As others have noted, sth is not allocated on the heap, but in the program's data segment, ie the compiler has already allocated the memory at compile time.
sth is probably in block static storage (a.k.a. "BSS", depending on platform):
Again, this is entirely "platform dependent", but there are generally four regions "segments" where you can allocate variable space from:
a) Heap: your language's runtime manages "heap" data, e.g. with calls to "malloc()" or "new")
b) Stack: these are "automatic" variables
c) BSS: unintialized (variable) static data
d) Data: initialized (and often read-only) static data
http://en.wikipedia.org/wiki/Data_segment
It depends on the implementation; arguments may be pushed onto the stack frame, or they may be written to registers, or they may be passed by some other mechanism.
The language definition does not mandate where various objects should be stored; it only mandates how those objects should behave.

Where are constant variables stored in C?

I wonder where constant variables are stored. Is it in the same memory area as global variables? Or is it on the stack?
How they are stored is an implementation detail (depends on the compiler).
For example, in the GCC compiler, on most machines, read-only variables, constants, and jump tables are placed in the text section.
Depending on the data segmentation that a particular processor follows, we have five segments:
Code Segment - Stores only code, ROM
BSS (or Block Started by Symbol) Data segment - Stores initialised global and static variables
Stack segment - stores all the local variables and other informations regarding function return address etc
Heap segment - all dynamic allocations happens here
Data BSS (or Block Started by Symbol) segment - stores uninitialised global and static variables
Note that the difference between the data and BSS segments is that the former stores initialized global and static variables and the later stores UNinitialised ones.
Now, Why am I talking about the data segmentation when I must be just telling where are the constant variables stored... there's a reason to it...
Every segment has a write protected region where all the constants are stored.
For example:
If I have a const int which is local variable, then it is stored in the write protected region of stack segment.
If I have a global that is initialised const var, then it is stored in the data segment.
If I have an uninitialised const var, then it is stored in the BSS segment...
To summarize, "const" is just a data QUALIFIER, which means that first the compiler has to decide which segment the variable has to be stored and then if the variable is a const, then it qualifies to be stored in the write protected region of that particular segment.
Consider the code:
const int i = 0;
static const int k = 99;
int function(void)
{
const int j = 37;
totherfunc(&j);
totherfunc(&i);
//totherfunc(&k);
return(j+3);
}
Generally, i can be stored in the text segment (it's a read-only variable with a fixed value). If it is not in the text segment, it will be stored beside the global variables. Given that it is initialized to zero, it might be in the 'bss' section (where zeroed variables are usually allocated) or in the 'data' section (where initialized variables are usually allocated).
If the compiler is convinced the k is unused (which it could be since it is local to a single file), it might not appear in the object code at all. If the call to totherfunc() that references k was not commented out, then k would have to be allocated an address somewhere - it would likely be in the same segment as i.
The constant (if it is a constant, is it still a variable?) j will most probably appear on the stack of a conventional C implementation. (If you were asking in the comp.std.c news group, someone would mention that the standard doesn't say that automatic variables appear on the stack; fortunately, SO isn't comp.std.c!)
Note that I forced the variables to appear because I passed them by reference - presumably to a function expecting a pointer to a constant integer. If the addresses were never taken, then j and k could be optimized out of the code altogether. To remove i, the compiler would have to know all the source code for the entire program - it is accessible in other translation units (source files), and so cannot as readily be removed. Doubly not if the program indulges in dynamic loading of shared libraries - one of those libraries might rely on that global variable.
(Stylistically - the variables i and j should have longer, more meaningful names; this is only an example!)
Depends on your compiler, your system capabilities, your configuration while compiling.
gcc puts read-only constants on the .text section, unless instructed otherwise.
Usually they are stored in read-only data section (while global variables' section has write permissions). So, trying to modify constant by taking its address may result in access violation aka segfault.
But it depends on your hardware, OS and compiler really.
offcourse not , because
1) bss segment stored non inilized variables it obviously another type is there.
(I) large static and global and non constants and non initilaized variables it stored .BSS section.
(II) second thing small static and global variables and non constants and non initilaized variables stored in .SBSS section this included in .BSS segment.
2) data segment is initlaized variables it has 3 types ,
(I) large static and global and initlaized and non constants variables its stord in .DATA section.
(II) small static and global and non constant and initilaized variables its stord in .SDATA1 sectiion.
(III) small static and global and constant and initilaized OR non initilaized variables its stord in .SDATA2 sectiion.
i mention above small and large means depents upon complier for example small means < than 8 bytes and large means > than 8 bytes and equal values.
but my doubt is local constant are where it will stroe??????
This is mostly an educated guess, but I'd say that constants are usually stored in the actual CPU instructions of your compiled program, as immediate data. So in other words, most instructions include space for the address to get data from, but if it's a constant, the space can hold the value itself.
This is specific to Win32 systems.
It's compiler dependence but please aware that it may not be even fully stored. Since the compiler just needs to optimize it and adds the value of it directly into the expression that uses it.
I add this code in a program and compile with gcc for arm cortex m4, check the difference in the memory usage.
Without const:
int someConst[1000] = {0};
With const:
const int someConst[1000] = {0};
Global and constant are two completely separated keywords. You can have one or the other, none or both.
Where your variable, then, is stored in memory depends on the configuration. Read up a bit on the heap and the stack, that will give you some knowledge to ask more (and if I may, better and more specific) questions.
It may not be stored at all.
Consider some code like this:
#import<math.h>//import PI
double toRadian(int degree){
return degree*PI*2/360.0;
}
This enables the programmer to gather the idea of what is going on, but the compiler can optimize away some of that, and most compilers do, by evaluating constant expressions at compile time, which means that the value PI may not be in the resulting program at all.
Just as an an add on ,as you know that its during linking process the memory lay out of the final executable is decided .There is one more section called COMMON at which the common symbols from different input files are placed.This common section actually falls under the .bss section.
Some constants aren't even stored.
Consider the following code:
int x = foo();
x *= 2;
Chances are that the compiler will turn the multiplication into x = x+x; as that reduces the need to load the number 2 from memory.
I checked on x86_64 GNU/Linux system. By dereferencing the pointer to 'const' variable, the value can be changed. I used objdump. Didn't find 'const' variable in text segment. 'const' variable is stored on stack.
'const' is a compiler directive in "C". The compiler throws error when it comes across a statement changing 'const' variable.

Resources