Function parameter by value vs reference memory managment - c

I am trying to understand C language, more specifically about memory managment. I have a function func that takes 1 argument, an int pointer. If I used int i instead of int *i it would allocate more memory because the value would be copied. Since I know that both func1 and func2 will not change the i variable, the result of those 2 functions is exactly the same.
What would happen if I called those functions many times ? Obviously the func1 would perform better, correct ? What about func2 ? Would it allocate new memory every time it is called ? So allocate 10000 * 4 extra bytes ? or just 4 extra bytes ?
I suppose it allocates 4 extra bytes, if it actually is, when is this memory allocated ? Is it when the function is first called ? Also, how and when will this 4(?) bytes of memory become free ?
void func1(int *i)
{
}
void func2(int i)
{
}
void main()
{
int x = 100;
for(int i = 0; i < 10000 ; i++) func1(&x);
for(int i = 0; i < 10000 ; i++) func2(x);
}

This is probably compiler-specific (you could look through the C spec to be sure), but the integer parameter should be allocated on the call stack for the function. Each time you call the function, there will be an extra 4 bytes allocated to work with that will be freed when the function returns.
For the reference version of the function, it will allocate space for the int pointer on each function call. Depending on your machine, that may be bigger, smaller, or the same size as an int. Compare sizeof(int) with sizeof(int*) to see which is bigger.

Let's talk about storage duration, which is the duration for which the object (region of data storage in the execution environment, the contents of which can represent values) named by a variable exists. Function arguments and local variables with no explicit storage duration or storage duration auto or register have automatic storage duration. That is, they are created when they are declared and are destroyed when the function containing them returns.
On function call the values specified for the arguments are copied into the automatic variables representing the arguments in the function definition. These variables are destroyed on function return so unless you recursively call yourself, you won't amass tons of memory. You shouldn't care about the difference between the size of an int and an int* either unless you have a lot of these. When in doubt, profile and change the code when it turns out that you have a problem.

The C standard does not specify how arguments are passed, however, in most C implementations, the memory used by arguments are automatically allocated and freed on the call stack, which has little overhead compared to heap allocation. Usually, memory is allocated on the stack as the arguments are passed, and freed before or when the function returns.
Both versions of function will allocate memory on the call stack. The reference version will allocate memory for the pointer. And the reference version is probably slower because it involves pointer dereference.

As the risk of over simplification and looking at practicable implementation, there is generally no performance or memory difference between
void func1(int *i)
void func2(int i)
A compiler is going to implement the former something like
PUSHAL I(SP)
CALL func1
and the latter like
PUSHL I(SP)
CALL func2
For atomic values, there simply is not going to be much difference. Change to
struct somestruct
{
char buffer [20000] ;
} ;
In that case
void func3(somestruct *i)
is likely to be much faster than
void func3 (somestruct i)
because the amount of data to be copied is much greater.

Related

Returning an array of variable size in c from a function

So i want to return an array of a size n (variable) which my function has as input. I know that in order to return arrays in C I have to define them static, but the problem is that n is a variable and thus I get an error. I thought of actually using malloc/calloc but then I won't be able to free them after the function returns the array. Please take note that I'm not allowed to change anything on main(). Are there any other alternatives which I could use? Thanks in advance.
float *Arr( int *a , int n ){
static float b[ n ];
return b
}
Got to point out that the function will only be called Once,I saw the solution you posted but i noticed you aren't freeing the allocated memory,is it not of much importance when the malloc is called inside a function?
The important thing to notice here is that this syntax:
float arr[n];
Allocates an array on the stack of the current function. In other words, that array is a local variable. Any local variable becomes invalid after the function returns, and therefore returning the array directly is undefined behavior. It will most likely cause a crash when trying to access the array from outside the function, if not anything worse.
In addition to that, declaring a variable-length array as static is invalid in any case.
If you want to write a function which creates and returns any kind of array (dynamically sized or not), the only option you have is to use dynamic allocation through malloc() and then return a pointer to the array (technically there's also alloca() to make dynamic stack allocations, but I would avoid it as it can easily break your program if the allocation is too large).
Here's an example of correct code:
float *create_array(size_t n_elements){
float *arr = malloc(sizeof(float) * n_elements);
if (arr == NULL) {
// Memory could not be allocated, handle the error appropriately.
}
return arr;
}
In this case, malloc() is reserving memory outside of the local stack of the function, in the heap. The result is a pointer that can be freely returned and passed around without any problem, since that area of memory keeps being valid after the function returns (until it is released). When you're done working with the data, you can release the allocated memory by calling free():
float *arr = create_array(100);
// ...
free(arr);
If you don't have a way to release the memory through free() after using malloc(), that's a problem in the long run, but in general, it is not a strict requirement: if your array is always needed, from its creation until the exit of the program, then there's no need to explicitly free() it, since memory is automatically released when the program terminates.
If your function needs to be called more than once or needs to create significantly sized arrays that are only useful in part of the program and should therefore be discarded when no longer in use, then I'm afraid there's no good way of doing it. You should use free() in that case.
To answer your question precisely:
Please take note that I'm not allowed to change anything on main(). Are there any other alternatives which I could use?
No, there are no other better alternatives. The only correct approach here is to dynamically allocate the array through malloc(). The fact that you cannot free it afterwards is a different kind of problem.
So i want to return an array of a size n(variable) which my function
has as input,
You can't, because C functions cannot return arrays at all. They can, and some do, return pointers, however, as your function is declared to do. Such a pointer may point to an element of an array.
i know that in order to return arrays in c i have to
define them static,
As long as I am being pedantic, the problem is to do with the lifetime of the object to which the returned pointer points. If it is an element of an automatically-allocated array, then it, along with the rest of the array, ceases to exist when the function returns. The caller must not try to dereference such a pointer.
The two other alternatives are
static allocation, which you get by declaring the variable static or by declaring it at file scope, and
dynamic allocation, which you get by reserving memory via malloc(), calloc(), or a related function.
Statically allocated objects exist for the entire lifetime of the program, and dynamically allocated ones exist until deallocated.
but problem is that n is a variable and thus i get
an error.
Yes, because variable-length arrays must be automatically allocated. Static objects exist for the whole run of the program, so the compiler needs to reserve space for them at compile time.
I thought of actually using malloc/calloc but then i won't be
able to free them after the function returns the array.
That's correct, but dynamic allocation is still probably the best solution. It is not unreasonable for a called function to return a pointer to an allocated object, thus putting the responsibility on its caller to free that object. Ordinarily, that would be a well-documented characteristic of the function, so that its callers know that such responsibility comes with calling the function.
Moreover, although it's a bit untidy, if your function is to be called only once then it may be acceptable to just allow the program to terminate without freeing the array. The host operating system can generally be relied upon to clean up the mess.
Please take
note that im not allowed to change anything on main(),are there any
other alternatives which i could use?
If you have or can impose a bound on the maximum value of n then you can declare a static array of that maximum size or longer, and return a pointer to that. The caller is receiving a pointer, remember, not an array, so it can't tell how long the pointed-to array actually is. All it knows is that the function promises n accessible elements.
Note well that there is a crucial difference between the dynamic allocation and static allocation alternatives: in the latter case, the function returns a pointer to the same array on every call. This is not inherently wrong, but it can be problematic. If implemented, it is a characteristic of the function that should be both intentional and well-documented.
If want an array of n floats where n is dynamic, you can either create a
variadic-length array (VLA):
void some_function(...)
{
//...
float b[ n ]; //allocate b on the stack
//...
}
in which case there would be no function call for the allocation, or you can allocate it dynamically, e.g., with malloc or calloc, and then free it after you're done with it.
float *b = malloc(sizeof(*b)*n);
A dynamic (malloc/calloc) allocation may be wrapped in a function that returns a pointer to the allocated memory (the wrapper may do some initializations on the allocated memory after the memory has been successfully allocated). A VLA allocation may not, because a VLA ends its lifetime at the end of its nearest enclosing block (C11 Standard - 6.2.4 Storage durations of objects(p7)).
If you do end up wrapping a malloc/calloc call in a "constructor" function like your float *Arr(void), then you obviously should not free the to-be-returned allocated memory inside Arr–Arr's caller would be responsible for freeing the result (unless it passed the responsibility over to some other part of the program):
float *Arr( int n, ...
/*some params to maybe initialize the array with ?*/ )
{
float *r; if (!(r=malloc(sizeof(*r)*n)) return NULL;
//...
//do some initializations on r
//...
return r; //the caller should free it
}
you could use malloc to reserve memory for your n sized array
Like this:
#include <stdlib.h>
#include <stdio.h>
float * arr(int * a, int n ) {
float *fp = malloc ( (size_t) sizeof(float)*n);
if (!fp) printf("Oh no! Run out of memory\n");
return fp;
}
int main () {
int i;
float * fpp = arr(&i,200);
printf("the float array is located at %p in memory\n", fpp);
return(0);
}
It seems like what you want to do is:
have a function that provides (space for) an array with a variable number of elements,
that the caller is not responsible for freeing,
that there only needs to be one instance of at a time.
In this case, instead of attempting to define a static array, you can use a static pointer to manage memory allocated and freed with realloc as needed to adjust the size, as shown in the code below. This will leave one instance in existence at all times after the first call, but so would a static array.
This might not be a good design (it depends on circumstances not stated in the question), but it seems to match what was requested.
#include <stdio.h>
#include <stdlib.h>
float *Arr(int *a , int n)
{
// Keep a static pointer to memory, with no memory allocated initially.
static float *b = NULL;
/* When we want n elements, use realloc to release the old memory, if any,
and allocate new memory.
*/
float *t = realloc(b, n * sizeof *t);
// Fail if the memory allocation failed.
if (!t)
{
fprintf(stderr, "Error, failed to allocate memory in Arr.\n");
exit(EXIT_FAILURE);
}
// Return the new memory.
return b;
}

Free memory in a function

Which it is the correct way to release the memory in this case; there is some difference between the two methods?
void allocateArray1(int size, int value)
{
int* arr = malloc(size * sizeof(int));
/* ... */
free(arr);
}
int* allocateArray2(int size, int value)
{
int* arr = malloc(size * sizeof(int));
/* ... */
return arr;
}
int main()
{
int* vector = allocateArray2(5,45);
free(vector);
allocateArray1(5,45);
return 0;
}
They are equivalent, because both allocation with malloc and release with free. The allocateArray1 method does it all in one function, which makes it easier to remember to free the memory. But sometimes you need the function to provide main (or some other function) with memory, so it can use it. In that case you'll just have to delete it later, as in the allocateArray2 method.
This is sometimes what's known as “ownership semantics”, i.e. who owns the object (and therefore who is responsible for freeing the object).
Some functions require the caller to free the returned object, e.g. strdup(), or sometimes the POSIX getline() function too. In these cases, the strdup() and getline() functions can't know what you plan to do with the result or how long you'll need the result for, so they delegate the task of freeing the object to the caller of the function.
Other library functions may return an object whose lifetime is already maintained by the library itself, so there is no need to free anything.
It's important when developing a project to have consistent ownership semantics. For example, perhaps any function that delegates the task of freeing objects could start with alloc (or new or create etc.), and then you'll always know that freeing the result of these functions is your responsibility. It's not really important how the ownership semantics are defined, as long as they are consistent.
Which it is the correct way to release the memory in this case; there is some difference between the two methods?
Both methods are correct.
However, i will prefer to use int* allocateArray2(int size, int value) function which allocates some memory from the heap inside the function and return pointer to allocated memory space.
The primary reason malloc is needed is when you have data that must have a lifetime that is different from code scope. Your code calls malloc in one routine, stores the pointer somewhere and eventually calls free in a different routine.
void allocateArray1(int size, int value) function which asks for some memory, does some processing and frees the memory before returning is not the efficient method if the size is less. You can instead create the array on the stack and use it for further processing. The advantage of using the stack to store variables, is that memory is managed for you. You don't have to allocate memory by hand, or free it once you don't need it any more. What's more, because the CPU organizes stack memory so efficiently, reading from and writing to stack variables is very fast. However, it may cause stack overflow, if you attempt to allocate more memory on the stack than will fit, for example by creating local array variables that are too large.
An example of a very large stack variable in C:
int foo()
{
double x[1048576];
}
The declared array consumes 8 mebibytes of data (assuming each double is 8 bytes); if this is more memory than is available on the stack (as set by thread creation parameters or operating system limits), a stack overflow will occur.

If I define an array in if statement then does memory get allocated?

If I define an array in if statement then does memory gets allocated during compile time eg.
if(1)
{
int a[1000];
}
else
{
float b[1000];
}
Then a memory of 2 * 1000 for ints + 4 * 1000 for floats get allocated?
It is reserved on the stack at run-time (assuming a non-trivial condition - in your case, the compiler would just exclude the else part). That means it only exists inside the scope block (between the {}).
In your example, only the memory for the ints gets allocated on the stack (1000 * sizeof(int)).
As you can guess, this is happening at run time. The generated code has instructions to allocate the space on the stack when the corresponding block of code is entered.
Keep in mind that this is happening because of the semantics of the language. The block structure introduces a new scope, and any automatic variables allocated in that scope have a lifetime that lasts as long as the scope does. In C, this is implemented by allocating it on the stack, which collapses as the scope disappears.
Just to drive home the point, note that the allocation would be different had the variables been of different nature.
if(1)
{
static int a[1000];
}
else
{
static float b[1000];
}
In this case, space is allocated for both the ints and the floats. The lifetime of these variables is the program. But the visibility is within the block scope they are allocated in.
Scope
Variables declared inside the scope of a pair of { } are on the stack. This applies to variables declared at the beginning of a function or in any pair of { } within the function.
int myfunc()
{
int i = 0; // On the stack, scoped: myfunc
printf("%i\n");
if (1)
{
int j = 1; // On the stack, scope: this if statement
printf("%i %i\n",i,j);
}
printf("%i %i\n",i,j); // Won't work, no j
}
These days the scope of the variables is limited to the surrounding { }. I recall that some older Microsoft compilers didn't limit the scope, and that in the example above the final printf() would compile.
So Where is it in memory?
The memory of i and j is merely reserved on the stack. This is not the same as memory allocation done with malloc(). That is important, because calling malloc() is very slow in comparison. Also with memory dynamically allocated using malloc() you have to call free().
In effect the compiler knows ahead of time what space is needed for a function's variables and will generate code that refers to memory relative to whatever the stack pointer is when myfunc() is called. So long as the stack is big enough (2MBytes normally, depends on the OS), all is good.
Stack overflow occurs in the situation where myfunc() is called with the stack pointer already close to the end of the stack (i.e. myfunc() is called by a function which in turn had been called by another which it self was called by yet another, etc. Each layer of nested calls to functions moves the stack pointer on a bit more, and is only moved back when functions return).
If the space between the stack pointer and the end of the stack isn't big enough to hold all the variables that are declared in myfunc(), the code for myfunc() will simply try to use locations beyond the end of the stack. That is almost always a bad thing, and exactly how bad and how hard it is to notice that something has gone wrong depends on the operating system. On small embedded micro controllers it can be a nightmare as it usually means some other part of the program's data (eg global variables) get silently overwritten, and it can be very hard to debug. On bigger systems (Linux, Windows) the OS will tell you what's happened, or will merely make the stack bigger.
Runtime Efficiency Considerations
In the example above I'm assigning values to i and j. This does actually take up a small amount of runtime. j is assigned 1 only after evaluation of the if statement and subsequent branch into where j is declared.
Say for example the if statement hadn't evaluated as true; in that case j is never assigned 1. If j was declared at the start of myfunc() then it would always get assigned the value of 1 regardless of whether the if statement was true - a minor waste of time. But consider a less trivial example where a large array is declared an initialised; that would take more execution time.
int myfunc()
{
int i = 0; // On the stack, scoped: myfunc
int k[10000] = {0} // On the stack, scoped: myfunc. A complete waste of time
// when the if statement evaluates to false.
printf("%i\n");
if (0)
{
int j = 1; // On the stack, scope: this if statement
// It would be better to move the declaration of k to here
// so that it is initialised only when the if evaluates to true.
printf("%i %i %i\n",i,j,k[500]);
}
printf("%i %i\n",i,j); // Won't work, no j
}
Placing the declaration of k at the top of myfunc() means that a loop 10,000 long is executed to initialise k every time myfunc() is called. However it never gets used, so that loop is a complete waste of time.
Of course, in these trivial examples compilers will optimise out the unnecessary code, etc. In real code where the compiler cannot predict ahead of time what the execution flow will be then things are left in place.
Memory for the array in the if block will be allocated on stack at run time. else part will be optimized (removed) by the compiler. For more on where the variables will be allocated memory, see Segmentation Fault when writing to a string
As DCoder & paddy corrected me, the memory will be calculated at compile time but allocated at run-time in stack memory segment, but with the scope & lifetime of the block in which the array is defined. The size of memory allocated depends on size of int & float in your system. Read this for an overview on C memory map

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.

How to locally allocate array-pointer in C?

Think of a pointer-datatype, for instance to a floating-pointer number.
typedef float* flPtrt;
How would I allocate an array of 3 elements in the local scope? I guess using malloc and free withing the same scope produces overhead, but what's the alternative?
void foo() {
flPtrt ptr = malloc(sizeof(float)*3);
// ...
free(ptr);
}
If 3 is known at compile time and is small enough, you can declare a local array and use it as a pointer
void foo() {
float array[3];
flPtrt ptr = array;
}
If the size is bigger or variable, you have to use dynamic memory as in your example.
I think what your'e looking for is the alloca() function.
I'm not sure it's standard C, but it exists in GNU, and it worked on my visual studio.
So this is how you use it:
int n = 5;
int* a = (int*) alloca(sizeof(int) * n);
It creates an array of elements on the stack (rather than on the heap with malloc).
Advantages: less overhead, no need to free manually (when you return from your method, the stack folds back and the memory is lost)
Disadvantage: If you want to return a pointer from a method NEVER use alloca, since you will be pointing at something that no longer exists after exiting the function. One can also argue that the stack is usually smaller than the heap, so if you want larger space use malloc.
See more here
If you know the required size of the array ahead of time, you could just allocate it as a stack variable and avoid heap memory management.
Otherwise, the approach you outlined is appropriate and there is not really an alternative.
Use an array.
void foo(void) // note that "void foo()" is obsolete
{
float data[3];
float *ptr = data;
// ...
}

Resources