Arrays as parameters and inputs in c - c

Okay so I understand that a function cannot return an array but rather a pointer to an array but I had other questions.
Does the array that I am going to be pointing to need to be declared outside the function?
If I dynamically allocate memory for an array in this function, would I able to free it within a function that called this function?
Say intended to loop this function in a for loop would this be acceptable/ideal as long as I freed the memory before calling It again.

yes you can free the dynamically allocated memory for the array from the calling function. it is fine provided you allocated memory on heap using function like malloc(). Then you can free that memory from any function if you have a pointer to that memory using free().

You can return an array of a function if you know
that the memory exists further and you´re freeíng it if nessecary.
Rough possible cases:
A non-dynamic array outside of the function can be passed to it.
The function could return the same array (it makes no sense,
beauce the caller should have it alaready, but it is possible)
A non-dynamic array of a function can NOT be returned to the outside
because it will cease to exist at the end of the function.
A dynamic allocated array from anywhere can be passed/returned as much as you want,
as long you know when and where it will be free´d
(ie. don´t forget the free and don´t access it after the free)

Related

Malloc in C copying previously allocated strings?

When i use malloc in C, i use it within different functions and free the pointers i used in malloc outside of the function.
Function 1: allocates memory for a point that is a string "hi" it returns the pointer that has "hi"
function 2: I have a pointer and allocate memory for this pointer, it then contains "hi" too. Even though i haven't done anything to this pointer.
Why does this happen? How do i stop this?
I've tried to reallocate memory and free multiple times but nothing works.
Your question is unclear. If you are allocating memory with malloc, the library does not initialize the memory to which a pointer is returned. It may contain anything: in your case, it may well contain the same string, but is does not mean anything.
Post your code so we can confirm this diagnostic.

C programming, using memory

I have a main function and it has global array
unsigned int MainArray [800];
then the program calls function which has local
unsigned int FunctionArray [400];
and I have not enough space in memory.
However the MainArray is not used while the function is called and inside data is not important, also FunctionArray is not required after function is used.
Is any way how FunctionArray can be declared over same memory allocation that the MainArray uses?
When I declare MainArray [800]; inside main then later on other functions can’t access the data.
If you want the data from the mainArray on the later state of the program, i.e, after the execution of the function, then, you can't say the "data of the mainArray is not important while the function is called" because it's important afterwards.
If you are thinking of a way for "FunctionArray can be declared over same memory allocation that the MainArray uses", then even if there WOULD HAVE BEEN a way, the data of mainArray would have been destroyed which you will be needing in later program as you said.
If you don't need the data of main in later state, you can do one thing,
define the array as a pointer outside the main(),
unsigned int * MainArray;
then allocate it dynamically with required size in main(). When the need of the array is finished, just free the memory. The space will be available for farther allocations.
If you need the mainArray after the execution of the function having the functionArray,and not before; just allocate the memory for the mainArray after the function has been executed. and use the local functionArray as the pointer as well, in the function and free the memory before the control gets back from the function. This way your program doesn't occupy the space for the mainArray while executing that function, and when the function is done executing, functionArray is not occupying any space.
But if you need mainArray, both before and after the function execution, I think there is no way you could solve the memory problem..
If you declare a variable inside main(), this doesn't make it a global variable, it's a variable local to main(). Unless you pass a pointer to it around, other functions can't access it.
You seem to ask for a global array. Just declare it outside main() and every function can access it.
Global variables, however, should be carefully considered since they vulnerate the rule of information hiding/encapsulation (that may be the reason nobody taught you they exist), nevertheless there are sometimes good reasons to use them (especially on devices where memory is a scarce resource which seems to be the case for you).
you can use the arrays base pointer to access the array's memory space in other functions.
you declare a array
unsigned int MainArray [800];
Then if you pass MainArray as parameter to function and receive it as,
returnType somefunction(unsigned int * FunctionArray, ...)
{
}
Then you can use the same memory in both main function and array. but in function make sure that you access FunctionArray only within its size limit of 400. This will enable you to access same memory in both functions as array.
You can even allocate memory to arrays dynamically, if they are needed in program in sequence and not at same time. you can use malloc or alloca.

Can you define an array on the stack and pass the pointer to a global variable?

I'm programming C on a microchip that doesn't support any memory allocation commands, but it does like pointers (of course). So my question is:
Is there a way to define an array within a function, and pass the pointer to that array back to a global variable?
This would be a way to have a dynamic memory use WITHOUT malloc, realloc, or calloc. Essentially stack memory being passed back to global WITHOUT it destroying itself. I'm assuming that the alloc commands are specifically needed to ensure it doesn't get destroyed, but I wanted to check and see if there was a way around this.
Yes you can declare arrays in functions. The memory for the array will be on the call stack - though be careful, no malloc is often accompanied by a small stack.
Yes, you can give the address of a locally declared array to a globally declared pointer.
Yes it can be a handy source of dynamic memory in some circumstances, but whether you are declaring a local array or calling the much maligned alloca function the result it the same.
But, the memory is only safe until you return from the function the array is in, so you can't turn this into a malloc style thing, but rather only generate memory/scratch for your call children.
You would need to define a huge global array to reserve a big chunk of memory then use that array instead. If you prefer you can also write some simple alloc/free function to allocate/free blocks from that array.
Stack memory will be reused by the next function call. So it is not possible for you to keep anything after the function returns. Of course, if you know your function won't return while that variable is used (for example, a local variable of the main function), then it's safe to pass the pointer to that variable around.
You could define the array as static in the function and assign the value to a global pointer. Not sure I would call this a good programming practice.
Note that this only gets you 1 copy of the array so subsequent calls to your function won't create additional instances of your array. In which case I would ask why don't you just make the array global in the first place?
Do you mean something like this?
char* x;
int main(int argc, char** argv) {
static char foo[80];
x = foo;
// ...
}
This puts your buffer in the BSS segment. If you want it to remain on the runtime stack, get rid of the static.
foo has automatic storage (basically, it's size is fixed), but you now have a globally visible pointer to it.
It will hold until main returns, which presumably, is the end of your process and you don't need it anymore.
If you want to have truly dynamic memory, you'll have to write your own memory allocator, as suggested in the comments.
It's possible to store the address of an object with automatic storage duration (your array "on the stack") in a global variable, but this does not in any way increase the lifetime of the object. It still ceases to exist when execution of the block in which it's declared ends. And after it ceases to exist, any further use of the pointer you stored in your global variable would result in undefined behavior.
The main problem is function calls and how calls affect stack. On IBM architecture, simply, current EBP pushed to stack, caller stack frame is saved to EBP and callee parameters pushed to stack(generally). On return pushed EBP is poped and stack allocated parameters could be overwritten by caller, that area is free to use since callee is returned.
When you some how dynamically allocate some space on stack, it's a possibility to overwrite that space somewhere in time at a function call which has some wide veriaty of parameters or recursive calls. This is why all dynamic allocations happens in Heap and heap management is at the hands of operating system. Since malloc (etc) is o.s. wrappers for heap allocations you do not need to worry about that management, o.s. will take it care for you.
If you want to achieve dynamic allocations on stack you need to go with assembly. Make sure allocate enough space before a function call at the caller site and take that space back when caller will be returned to its caller. And that organisation would be a brainfk i guess..
A simple way to allocate memory on the "stack", pass its address to a global memory.
A potential reason to do so would be to create a "State" (Set of data), but to not have to pass it to sub-functions as the nesting could be very deep and stack savings may be had. The price in that multi-threaded applications could not use Function() safely.
Notice that anything that calls Function() should not use State.
static char *State;
static int FunctionFoo_Helper(void) {
if (*State != '\0') {
// Do _something_ more interesting than simply print
printf("%c", *State++);
FunctionFoo_Helper();
}
}
void Function(size_t n) {
char Array[n]; // Variable size array
// As to if the system put this on the stack or elsewhere is system dependent.
Populate Array(Array);
Array[n-1] = '\0';
State = Array;
FunctionFoo_Helper();
}

ANSI C, Garbage Collector and Function enviroment Arrays, Exiting the function will cancel the array?

I need to code a function in which i declare a new array and then i need that array to stay in the memory...
I was wondering which is the best programming practice to attain this result, and i would also love to understand how does the garbage collector work in this specific situation
More in the case, if i declare a function and inside it i inizializate an array, if i keep the reference to the address outside the function, Once the function as finished working, and it's enviroment cease to exist, will the Array still be usable, or do i risk that further malloc or array declaration would unexpectdly override my previuos array?
also, if i use a malloc inside a function, will the memory allocated stay reserved untill i free it no matter where i do use the malloc?
Thanks for the help anyone will offer.
There is no garbage collection in C!
You should read a book about C: The Definitive C Book Guide and List, specifically about pointers, the heap and the stack.
If you malloc a section of memory, the pointers live on the heap, and will not disappear or "become unusable" until free is called on that pointer. It has nothing to do with the scope of a function, which is also called a stack frame. If you declared an array of a fixed size on the stack then it would go out of scope once that stack unwinds.
In short, your last sentence is correct, if you use malloc, the memory will be allocated on the heap until you call free.

malloc and scope

I am struggling to wrap my head around malloc in c - specifically when it needs to be free()'d. I am getting weird errors in gcc such as:
... free(): invalid next size (fast): ...
when I try to free a char pointer. For example, when reading from an input file, it will crash on certain lines when doing the following:
FILE *f = fopen(file,"r");
char x[256];
while(1) {
if(fgets(x,sizeof x,f)==NULL) break;
char *tmp = some_function_return_char_pointer(x); //OR malloc(nbytes);
// do some stuff
free(tmp); // this is where I get the error, but only sometimes
}
I checked for obvious things, such as x being NULL, but it's not; it just crashes on random lines.
But my REAL question is - when do I need to use free()? Or, probably more correctly, when should I NOT use free? What if malloc is in a function, and I return the var that used malloc()? What about in a for or while loop? Does malloc-ing for an array of struct have the same rules as for a string/char pointer?
I gather from the errors I'm getting in gcc on program crash that I'm just not understanding malloc and free. I've spent my quality time with Google and I'm still hitting brick walls. Are there any good resources you've found? Everything I see says that whenever I use malloc I need to use free. But then I try that and my program crashes. So maybe it's different based on a variable's scope? Does C free the memory at the end of a loop when a variable is declared inside of it? At the end of a function?
So:
for(i=0;i<100;i++) char *x=malloc(n); // no need to use free(x)?
but:
char *x;
for(i=0;i<100;i++) {
x=malloc(n);
free(x); //must do this, since scope of x greater than loop?
}
Is that right?
Hopefully I'm making sense...
malloc() is C's dynamic allocator. You have to understand the difference between automatic (scoped) and dynamic (manual) variables.
Automatic variables live for the duration of their scope. They're the ones you declare without any decoration: int x;
Most variables in a C program should be automatic, since they are local to some piece of code (e.g. a function, or a loop), and they communicate via function calls and return values.
The only time you need dynamic allocation is when you have some data that needs to outlive any given scope. Such data must be allocated dynamically, and eventually freed when it is no longer necessary.
The prime usage example for this is your typical linked list. The list nodes cannot possibly be local to any scope if you are going to have generic "insert/erase/find" list manipulation functions. Thus, each node must be allocated dynamically, and the list manipulation functions must ensure that they free those nodes that are no longer part of the list.
In summary, variable allocation is fundamentally and primarily a question of scope. If possible keep everything automatic and you don't have to do anything. If necessary, use dynamic allocation and take care to deallocate manually whenever appropriate.
(Edit: As #Oli says, you may also want to use dynamic allocation in a strictly local context at times, because most platforms limit the size of automatic variables to a much smaller limit than the size of dynamic memory. Think "huge array". Exceeding the available space for automatic variables usually has a colourful name such as "pile overrun" or something similar.)
In general, every call to malloc must have one corresponding call to free.* This has nothing to do with scope (i.e. nothing to do with functions or loops).
* Exceptions to this rule include using functions like strdup, but the principle is the same.
Broadly speaking, every pointer that is ever returned by malloc() must eventually be passed to free(). The scope of the variable that you store the pointer in does not affect this, because even after the variable is no longer in scope, the memory that the pointer points to will still be allocated until you call free() on it.
Well, the scope of the malloc'd memory lays between calls to malloc and free or otherwise until process is stopped (that is when OS cleans up for the process). If you never call free you get a memory leak. That could happen when address that you can pass to free goes out of scope before you actually used it - that is like loosing your keys for the car, car is still there but you can't really drive it. The error you are getting is most likely either because function returns a pointer to some memory that was not allocated using malloc or it returns a null pointer which you pass to free, which you cannot do.
You should free memory when you will no longer be accessing it. You should not free memory if you will be accessing it. This will give you a lot of pain.
If you don't want memory leak, you have to free the memory from malloc.
It can be very tricky. For example, if the // do some stuff has a continue, the free will be skipped and lead to memory leak. It is tricky, so we have shared_ptr in C++; and rumor has it salary of C programmer is higher than C++ programmer.
Sometimes we don't care memory leak. If the memory holds something that is needed during the whole lifetime of execution, you can choose not to free it. Example: a string for environment variable.
PS: Valgrind is a tool to help detect memory bugs. Especially useful for memory leak.
malloc(n) allocates n bytes of memory from a memory location named heap and then returns a void* type of pointer to it. The memory is allocated at runtime. Once you have allocated a memory dynamically, scope does not matter as long as you keep a pointer to it with you(or the address of it specifically). For example:
int* allocate_an_integer_array(int n)
{
int* p = (int*) (malloc(sizeof(int)*n));
return p;
}
This functions simply allocates memory from heap equal to n integers and returns a pointer to the first location. The pointer can be used in the calling function as you want to. The SCOPE does not matter as long as the pointer is with you..
free(p) returns the memory to heap.
The only thing you need to remember is to free it as if you don't free it and lose the value of its address, there will bw a memory leak. It is so because according to OS, you are still using the memory as you have not freed it and a memory leak will happen..
Also after freeing just set the value of the pointer to null so that u don't use it again as the same memory may be allocated again at any other time for a different purpose....
So, all you need to do is to be careful...
Hope it helps!

Resources