Is memory will be destroyed or not? - c

Hi i have code like below , just added logic view not full syntax
int globalVar;
static void* average()
{
void *data = NULL;
if (true)
{
globalVar = getAverage();
data = ((void *)&globalVar);
}
return (data);
}
So my concern is if i return globel variable by assigning to local pointer then will it be in memory or lost when function end?
Thanks,

No there is no memory leak here. Memory leaks only arise from unbalanced malloc and free calls, and there is nothing like that going on here.
(Assuming getAverage() doesn't itself leak).

So my concern is if i return globel variable by assigning to local pointer then will it be in memory or lost when function end?
No.
If it's a global variable then it'll have static storage duration and it won't be "lost" when returning it through a local pointer.
When you access any object through a pointer, what matters is the storage duration of the object you access; not the storage duration of the pointer. So, assuming your global variable has static storage duration (usually defined outside functions at the top of source files), you are fine.

Related

Is it possible to initialize a struct within a function in C without dynamic memory allocation such that it persists after the function returns?

I am currently building a dynamic memory management class in C for a school project. As part of the initialization for my heap I want to initialize a Block struct into the free memory list. I cannot use dynamic memory allocation to do this (as it is against the rules). This design is entirely of my own creation, so my approach may just be flawed. Is it possible to do? Code below will clarify exactly what I am trying to do. Based on my understanding of how C handles variables, the memory location for newBlock will be up for grabs as soon as the function ends which could lead to issues later if it is overwritten.
int mm_init()
{
// Initialize memory. Don't worry about this.
mem_init();
// Initialize the heap.
// Also don't worry about this.
list_init(heap.freeBlocks);
list_init(heap.allocatedBlocks);
// Here is where the question applies.
Block newBlock = //initialize the block.
// freeBlocks is a pointer to a list struct.
list_insert(heap.freeBlocks, &newBlock);
// Don't worry about this either.
return -1;
}
You need to make sure the variable has what's called static storage duration.
Static storage duration means that the object will be allocated in one fell swoop along with other objects with static storage duration at program start and will never be deallocated as long as the program lives.
There are 3 ways to give a C object the static storage duration.
Make it global -- this will make it accessible from other translation units as well
Block newBlock;
int mm_init() {
/* ... */
}
Make it global and mark it static -- this will make the identifier only accessible from the current translation unit
static Block newBlock;
int mm_init() {
/* ... */
}
Make it local and mark it static -- this will prevent the identifier from being accessible outside its enclosing function
int mm_init() {
static Block newBlock;
/* ... */
}

global declaration is in stack or heap?

I need to declare a variable that is not in the stack memory but in the heap, like below
struct mystruct *name;
Should I declare it outside all functions (even outside main()) at the begin of file?
Please note that a variable is never declared "on the heap". Only memory pointed to by a pointer can be allocated on (from) the heap.
In your example, you can declare name indeed outside any function and then it will exist in global memory. You can also delcare the variable inside a function, preceded by the keyword static. This latter will allocate the variable also in global memory, but it will only be visible in the function where you declared it.
To use your pointer variable, you now must alocate memory for it to point to, which you allocate on the heap using malloc.
TL;DR Version
You cannot declare a variable such that the variable itself lives on the heap.
James Michener Version
The C language definition doesn't talk about stacks or heaps; it talks about storage durations.
Objects with auto storage duration (anything declared within a block and without the static keyword) have lifetimes that extend from the beginning of that block and end when the block exits1:
void foo( void )
{
int a = 0; // lifetime of a extends to the end of
// the function
for ( int i = 0; i < 10; i++ ) // lifetime of i and b extend to the end
{ // of the for loop
int b = a + i;
printf( "b = %d\n", b );
}
}
Most implementations allocate storage for auto objects from the hardware stack, because a stack makes that behavior easy to implement2.
Objects with static storage duration (anything declared outside of a function or with the static keyword) have lifetimes that extend from the time the program is loaded into memory until the program exits:
int a = 0; // lifetime of a extends over the lifetime of
// the entire program
int main( void )
{
static int b = 10; // lifetime of b also extends over the lifetime
// of the program, but is only visible within
// main
...
}
Most implementations will set aside storage for static objects within the body of the executable itself (for an executable using the ELF format, such objects will be stored in the .bss, .data, or .rodata sections of the image).
Objects with allocated storage duration (anything allocated with malloc, calloc, or realloc) have lifetimes that extend from the time that they are allocated until they are explicitly deallocated with a call to free.
int *foo( size_t size )
{
int *ptr = malloc( sizeof *ptr * size );
return ptr;
}
void bar( void )
{
int *p = foo( 10 );
// do something with p
free( p );
}
The variables ptr and p only exist for the lifetimes of their respective functions, and they will be typically allocated from the stack. The object both variables point to exists from the time it is allocated with malloc until it is deallocated with free.
Most implementations allocate storage for allocated objects from the heap.
There's really no way for you to declare an object that has allocated storage duration; the only way you can create such an object is via malloc, calloc, or realloc. Whatever object you declare to store the pointer value returned by any of those functions will have either auto or static storage duration.
1. In practice, storage for all local objects is allocated at function entry and released at function exit, regardless of whether the object's lifetime is over the entire function or limited to a block within the function. However, you should never rely on that storage being accessible outside of that object's lifetime. For example, the lifetimes of i and b are limited to the for loop; even though the storage for each may have been allocated at function entry, you should not attempt to access that storage outside of the loop body.
2. C was designed on a machine with a stack, after all.

Global Pointer in C?

I know a pointer is usually assigned upon its declaration, but I wondering if there's any way to create a global pointer in C. For example my code below: is it a good practice?
static int *number_args = NULL;
void pro_init(int number)
{
number_args = &number; /* initialize the pointer value -- is this okay? */
}
Avoid globals - They are a bad idea and usually lead into problems.
You are taking an address of a variable on the stack. That will get reused somewhere down the line and hence having unintended results.
If you feel the need (why?) to have a global pointer then initialise if off the heap.
That is valid. There are many good reasons to have global variables, especially static global variables. But if something doesn't need to be global, it's better to not make it global.
Also keep in mind that if more than one thread accesses that variable, you'll need to protect it somehow, probably with a mutex, or you may have race conditions.
Also, keep in mind that "number" is a stack variable. Arguments to functions and local variables are both allocated on the stack, and cease to exist outside of their scope. So unless "pro_init()" either never returns, or sets the variable back to NULL before it returns, you'll end up with an invalid pointer.
You might use heap memory instead, for example:
number_args = malloc(sizeof(int));
if (number_args == NULL) { /* handle malloc error */ }
*number_args = number;

Static vs. Malloc

What is the advantage of the static keyword in block scope vs. using malloc?
For example:
Function A:
f() {
static int x = 7;
}
Function B:
f() {
int *x = malloc(sizeof(int));
if (x != NULL)
*x = 7;
}
If I am understanding this correctly, both programs create an integer 7 that is stored on the heap. In A, the variable is created at the very beginning in some permanent storage, before the main method executes. In B, you are allocating the memory on the spot once the function is called and then storing a 7 where that pointer points. In what type of situations might you use one method over the other? I know that you cannot free the x in function A, so wouldn't that make B generally more preferable?
Both programs create an integer 7 that is stored on the heap
No, they don't.
static creates a object with static storage duration which remains alive throughout the lifetime of the program. While a dynamically allocated object(created by malloc) remains in memory until explicitly deleted by free. Both provide distinct functionality. static maintains the state of the object within function calls while dynamically allocated object does not.
In what type of situations might you use one method over the other?
You use static when you want the object to be alive throughout the lifetime of program and maintain its state within function calls. If you are working in a multithreaded environment the same static object will be shared for all the threads and hence would need synchronization.
You use malloc when you explicitly want to control the lifetime of the object.for e.g: Making sure the object lives long enough till caller of function accesses it after the function call.(An automatic/local object will be deallocated once the scope{ } of the function ends). Unless the caller explicitly calls free the allocated memory is leaked until the OS reclaims it at program exit.
In Function A, you're allocating x with static storage duration, which generally means it is not on (what most people recognize as) the heap. Rather, it's just memory that's guaranteed to exist the entire time your program is running.
In Function B, you're allocating the storage every time you enter the function, and then (unless there's a free you haven't shown) leaking that memory.
Given only those two choices, Function A is clearly preferable. It has shortcomings (especially in the face of multi-threading) but at least there are some circumstances under which it's correct. Function B (as it stands) is just plain wrong.
Forget stack v. heap. That is not the most important thing that is going on here.
Sometimes static modifies scope and sometimes it modifies lifetime. Prototypical example:
void int foo() {
static int count = 0;
return count++;
}
Try calling this repeatedly, perhaps from several different functions or files even, and you'll see that count keeps increasing, because in this case static gives the variable a lifetime equal to that of the entire execution of the program.
Read http://www.teigfam.net/oyvind/pub/notes/09_ANSI_C_static_vs_malloc.html
The static variable is created before main() and memory does not need to be allocated after running the program.
If I am understanding this correctly, both programs create an integer 7 that is stored on the heap
No, static variables are created in Data or BSS segment, and they have lifetime throughout the lifetime of the program. When you alloc using malloc(), memory is allocated in heap, and they must be explicitly freed using free() call.
In what type of situations might you use one method over the other?
Well, you use the first method, when you want access to the same variable for the multiple invocation of the same function. ie, in your example, x will only initialized once, and when you call the method for the second time, the same x variable is used.
Second method can be used, when you don't want to share the variable for multiple invocation of the function, so that this function is called for the second time, x is malloced again.
You must free x every time.
You can see the difference by calling f() 2 times, for each kind of f()
...
f();
f();
...
f(){
static int x = 7;
printf("x is : %d", x++);
}
f(){
int *x = malloc(sizeof(int));
if (x != NULL)
*x = 7;
printf("x is : %d", (*x)++);
free(x); //never forget this,
}
the results will be different
First things first , static is a storage class , and malloc() is an API , which triggers the brk() system call to allocate memory on the heap.
If I am understanding this correctly, both programs create an integer
7 that is stored on the heap ?
No.Static variables are stored in the data section of the memory allocated to the program. Even though if the scope of a static variable ends , it can still be accessed outside its scope , this may indicate that , the contents of data segment , has a lifetime independent of scope.
In what type of situations might you use one method over the other?
If you want more control , within a given scope ,over your memory use malloc()/free(), else the simpler (and more cleaner) way is to use static.
In terms of performance , declaring a variable static is much faster , than allocating it on the heap . since the algorithms for heap management is complex and the time needed to service a heap request varies depending on the type of algorithm
One more reason i can think of suggesting static is that , the static variables are by default initialized to zero , so one more less thing to worry about.
consider below exaple to understand how static works. Generally we use static keyword to define scope of variable or function. e.g. a variable defined as static will be restricted within the function and will retail its value.
But as shown in below sample program if you pass the reference of the static variable to any other function you can still update the same variable from any other function.
But precisely the static variable dies when the program terminates, it means the memory will be freed.
#include <stdio.h>
void f2(int *j)
{
(*j)++;
printf("%d\n", *j);
}
void f1()
{
static int i = 10;
printf("%d\n", i);
f2(&i);
printf("%d\n", i);
}
int main()
{
f1();
return 0;
}
But in case of malloc(), memory will not be freed on termination of the program unless and untill programmer takes care of freeing the memory using free() before termination of the program.
This way you will feel that using malloc() we can have control over variable lifespan but beware...you have to be very precise in allocating and freeing the memory when you choose dynamic memory allocation.
If you forget to free the memory and program terminated that part of heap cannot be used to allocate memory by other process. This will probably lead to starvation of memory in real world and slows down the computation. To come out of such situation you have to manually reboot the system.

Why can a function return an array setup by malloc but not one setup by "int cat[3] = {0,0,0};"

Why can I return from a function an array setup by malloc:
int *dog = (int*)malloc(n * sizeof(int));
but not an array setup by
int cat[3] = {0,0,0};
The "cat[ ]" array is returned with a Warning.
Thanks all for your help
This is a question of scope.
int cat[3]; // declares a local variable cat
Local variables versus malloc'd memory
Local variables exist on the stack. When this function returns, these local variables will be destroyed. At that point, the addresses used to store your array are recycled, so you cannot guarantee anything about their contents.
If you call malloc, you will be allocating from the heap, so the memory will persist beyond the life of your function.
If the function is supposed to return a pointer (in this case, a pointer-to-int which is the first address of the integer array), that pointer should point to good memory. Malloc is the way to ensure this.
Avoiding Malloc
You do not have to call malloc inside of your function (although it would be normal and appropriate to do so).
Alternatively, you could pass an address into your function which is supposed to hold these values. Your function would do the work of calculating the values and would fill the memory at the given address, and then it would return.
In fact, this is a common pattern. If you do this, however, you will find that you do not need to return the address, since you already know the address outside of the function you are calling. Because of this, it's more common to return a value which indicates the success or failure of the routine, like an int, than it is to return the address of the relevant data.
This way, the caller of the function can know whether or not the data was successfully populated or if an error occurred.
#include <stdio.h> // include stdio for the printf function
int rainCats (int *cats); // pass a pointer-to-int to function rainCats
int main (int argc, char *argv[]) {
int cats[3]; // cats is the address to the first element
int success; // declare an int to store the success value
success = rainCats(cats); // pass the address to the function
if (success == 0) {
int i;
for (i=0; i<3; i++) {
printf("cat[%d] is %d \r", i, cats[i]);
getchar();
}
}
return 0;
}
int rainCats (int *cats) {
int i;
for (i=0; i<3; i++) { // put a number in each element of the cats array
cats[i] = i;
}
return 0; // return a zero to signify success
}
Why this works
Note that you never did have to call malloc here because cats[3] was declared inside of the main function. The local variables in main will only be destroyed when the program exits. Unless the program is very simple, malloc will be used to create and control the lifespan of a data structure.
Also notice that rainCats is hard-coded to return 0. Nothing happens inside of rainCats which would make it fail, such as attempting to access a file, a network request, or other memory allocations. More complex programs have many reasons for failing, so there is often a good reason for returning a success code.
There are two key parts of memory in a running program: the stack, and the heap. The stack is also referred to as the call stack.
When you make a function call, information about the parameters, where to return, and all the variables defined in the scope of the function are pushed onto the stack. (It used to be the case that C variables could only be defined at the beginning of the function. Mostly because it made life easier for the compiler writers.)
When you return from a function, everything on the stack is popped off and is gone (and soon when you make some more function calls you'll overwrite that memory, so you don't want to be pointing at it!)
Anytime you allocate memory you are allocating if from the heap. That's some other part of memory, maintained by the allocation manager. Once you "reserve" part of it, you are responsible for it, and if you want to stop pointing at it, you're supposed to let the manager know. If you drop the pointer and can't ask to have it released any more, that's a leak.
You're also supposed to only look at the part of memory you said you wanted. Overwriting not just the part you said you wanted, but past (or before) that part of memory is a classic technique for exploits: writing information into part of memory that is holding computer instructions instead of data. Knowledge of how the compiler and the runtime manage things helps experts figure out how to do this. Well designed operating systems prevent them from doing that.
heap:
int *dog = (int*)malloc(n*sizeof(int*));
stack:
int cat[3] = {0,0,0};
Because int cat[3] = {0,0,0}; is declaring an automatic variable that only exists while the function is being called.
There is a special "dispensation" in C for inited automatic arrays of char, so that quoted strings can be returned, but it doesn't generalize to other array types.
cat[] is allocated on the stack of the function you are calling, when that stack is freed that memory is freed (when the function returns the stack should be considered freed).
If what you want to do is populate an array of int's in the calling frame pass in a pointer to an that you control from the calling frame;
void somefunction() {
int cats[3];
findMyCats(cats);
}
void findMyCats(int *cats) {
cats[0] = 0;
cats[1] = 0;
cats[2] = 0;
}
of course this is contrived and I've hardcoded that the array length is 3 but this is what you have to do to get data from an invoked function.
A single value works because it's copied back to the calling frame;
int findACat() {
int cat = 3;
return cat;
}
in findACat 3 is copied from findAtCat to the calling frame since its a known quantity the compiler can do that for you. The data a pointer points to can't be copied because the compiler does not know how much to copy.
When you define a variable like 'cat' the compiler assigns it an address. The association between the name and the address is only valid within the scope of the definition. In the case of auto variables that scope is the function body from the point of definition onwards.
Auto variables are allocated on the stack. The same address on the stack is associated with different variables at different times. When you return an array, what is actually returned is the address of the first element of the array. Unfortunately, after the return, the compiler can and will reuse that storage for completely unrelated purposes. What you'd see at a source code level would be your returned variable mysteriously changing for no apparent reason.
Now, if you really must return an initialized array, you can declare that array as static. A static variable has a permanent rather than a temporary storage allocation. You'll need to keep in mind that the same memory will be used by successive calls to the function, so the results from the previous call may need to be copied somewhere else before making the next call.
Another approach is to pass the array in as an argument and write into it in your function. The calling function then owns the variable, and the issues with stack variables don't arise.
None of this will make much sense unless you carefully study how the stack works. Good luck.
You cannot return an array. You are returning a pointer. This is not the same thing.
You can return a pointer to the memory allocated by malloc() because malloc() has allocated the memory and reserved it for use by your program until you explicitly use free() to deallocate it.
You may not return a pointer to the memory allocated by a local array because as soon as the function ends, the local array no longer exists.
This is a question of object lifetime - not scope or stack or heap. While those terms are related to the lifetime of an object, they aren't equivalent to lifetime, and it's the lifetime of the object that you're returning that's important. For example, a dynamically alloced object has a lifetime that extends from allocation to deallocataion. A local variable's lifetime might end when the scope of the variable ends, but if it's static its lifetime won't end there.
The lifetime of an object that has been allocated with malloc() is until that object has been freed using the free() function. Therefore when you create an object using malloc(), you can legitimately return the pointer to that object as long as you haven't freed it - it will still be alive when the function ends. In fact you should take care to do something with the pointer so it gets remembered somewhere or it will result in a leak.
The lifetime of an automatic variable ends when the scope of the variable ends (so scope is related to lifetime). Therefore, it doesn't make sense to return a pointer to such an object from a function - the pointer will be invalid as soon as the function returns.
Now, if your local variable is static instead of automatic, then its lifetime extends beyond the scope that it's in (therefore scope is not equivalent to lifetime). So if a function has a local static variable, the object will still be alive even when the function has returned, and it would be legitimate to return a pointer to a static array from your function. Though that brings in a whole new set of problems because there's only one instance of that object, so returning it multiple times from the function can cause problems with sharing the data (it basically only works if the data doesn't change after initialization or there are clear rules for when it can and cannot change).
Another example taken from another answer here is regarding string literals - pointers to them can be returned from a function not because of a scoping rule, but because of a rule that says that string literals have a lifetime that extends until the program ends.

Resources