Initializing arrays in struct - c

So I decided to write my own Big Integer library for a microcontoller in C (the PIC32 if that matters), but I'm having a weird problem that I don't understand. When the code is run, the big_int_t structs a and b are at different memory locations, but a->bytes and b->bytes appear to be at the same location (confirmed by printing their pointers). Setting a value in b->bytes also changes the value in a->bytes. In the main function below, printing the first element from either struct's bytes array shows 41. Am I doing something wrong?
#include <stdint.h>
#include <stdio.h>
typedef struct {
uint8_t size;
uint8_t *bytes;
} big_int_t;
void big_init(big_int_t *big, uint8_t size) {
big->size = size;
uint8_t bytes[size];
big->bytes = bytes;
uint8_t i;
for(i=0;i<big->size;i++) big->bytes[i] = 0;
}
int main() {
big_int_t a,b;
big_init(&a,1);
big_init(&b,1);
a.bytes[0] = 16;
b.bytes[0] = 41;
printf("%d\n",a.bytes[0]);
printf("%d\n",b.bytes[0]);
}

In big_init the variable bytes is a local Variable, one that will go out of scope and disappear once the function returns. The pointer stored in big->bytes will become a stray pointer when the function returns, and dereferencing the pointer will lead to undefined behavior.
You can't use a local array for this, instead you need to allocate the array dynamically with malloc:
big->bytes = malloc(sizeof(*big->bytes) * big->size);
But don't forget to free the memory once you're done with it.

You are allocating your byte buffer on the stack:
uint8_t bytes[size];
When big_init exits the buffer is no longer valid. It will get randomly overwritten.
You probably want to dynamically allocate it using malloc(), but then you have to be careful to free it up again.

The reason for this behaviour is that you are assigning bytes with a pointer on the stack. When calling big_init for the first time, the local variable bytes will be placed on the stack and it's address will be used for bytes in the struct. Afterwards, you are calling the function big_init again. Now, the same stack as before is build up, and the local variable bytes is placed on the same location as before. Therefore, the two assignments lead to the same pointer.

Related

How do I define a struct and properly allocate memory for it in C?

I've recently started learning C and currently I'm working on a project which involves implementing a struct with two variables and I don't really know how to apparoach this.
The gist of it is I need to implement a struct which contains two variables, a pointer to an int array AND an int value which indicates the number of elements conatained within the array. The size of the array is declared upon the invocation of the constructor and is dependent on the input.
For the constructor I'm using a different function which recieves a string
as input which is encoded into a decimal code. Also this function recieves another input
which is a pointer to an int array (the pointer defined in the struct) and the problem is I'm using the malloc() function to allocate memory for it but I dont really understand how and when to use the free() function properly.
So, the questions are:
When am I supposed to free the allocated memory? (assuming I need this struct for later use throughout the program's running time)
What are the best ways to avoid memory leaks? What should you look out for?
It's unclear whether you're expected to manage the memory of the array inside, but this is functionally the setup you need for allocating the containing structure.
#include <malloc.h>
#include <stdio.h>
struct my_struct {
size_t num_entries;
int *array;
};
int main() {
struct my_struct *storage = malloc(sizeof(struct my_struct));
storage->num_entries = 4;
storage->array = malloc(sizeof(int) * storage->num_entries);
storage->array[0] = 1;
storage->array[3] = 2;
printf("allocated %ld entries\n", storage->num_entries);
printf("entry #4 (index=3): %d\n", storage->array[3]);
free(storage->array); /* MUST be first! */
free(storage);
storage = 0; /* safety to ensure you can't read the freed memory later */
}
if you're responsible for freeing the internal storage array, then you must free it first before freeing the containing memory.
The biggest key to memory management: only one part of the code at any time "owns" the memory in the pointer and is responsible for freeing it or passing it to something else that will.

When writing a function that returns pointer, why should I allocate memory to the pointer I'm going to return?

I'm a bit weak when it comes to memory allocation and pointers.
So, I want to understand why do I have to allocate memory to pointers in functions as follow:
char *cstring(char c, int n)
{
int i = 0;
char * res;
res = malloc ((n+1)*sizeof(char));
while (i<n)
{
res[i]=c;
i++;
}
res[i] ='\0';
return res;
}
and why is the following not valid?
char *cstring(char c, int n)
{
int i = 0;
char * res;
while (i<n)
{
res[i]=c;
i++;
}
res[i] ='\0';
return res;
}
I understand that I should allocate memory (generally) to pointers so that they have defined memory.
However, I want to mainly understand how is it related to the concept of stack and heap memories!
Thanks in advance!
Pointers need to point to a valid memory location before they can be dereferenced.
In your first example, res is made to point at a block of allocated memory which can subsequently be written to and read from.
In your second example, res remains uninitialized when you attempt to dereference it. This causes undefined behavior. The most likely outcome in this case is that whatever garbage value it happens to contain will not be a valid memory address, so when you attempt to dereference that invalid address your program will crash.
If you declare a variable like that,
int A = 5;
then that means the variable will be on the stack. When functions are called, their local variables are pushed to the stack. The main function is also an example of that. So you don't have to allocate memory manually, your compiler will do this for you in the background before it calls your main function. And that also means if you examine the stack during the execution of the function you can see the value 5.
With this,
int A = 5;
int *PtrToA = &A;
The pointer will be on the stack again. But this time, the value on the stack just shows the memory address of the actual integer value we want. It points to the address of the memory block that holds the value 5. Since A is held in the stack here, pointer will show a memory address on the stack.
Like the case in your question you can allocate memory dynamically. But you have to initialize it before you read it. Because when you request to allocate the memory, your operating system searches for a valid memory field in your programs heap and reserves that for you. Than it gives you back its adddress and gives you the read write permissions so you can use it. But the values in it won't contain what you want. When compiler allocates on stack, the initial values will be unset again. If you do this,
char *res;
res[1] = 3;
variable res will be on the stack and it will contain some random value. So accessing it is just like that,
(rand())[1] = 3;
You can get an access violation error because you may not have permission to write to that memory location.
An important note; after your function call returns, values of local variables on the stack are no more valid. So be careful with that. Do not dereference them after the function call ends.
In conclusion; if you want to use a pointer, be sure it points to a valid memory location. You can allocate it yourself or make it point another memory address.
The second version of your code declares a pointer, but does not initialize it to point to a valid memory address.
Then, the code dereferences that pointer -- during the loop. So, your code would access uninitialized memory in this case. Remember, array indexing is just syntactic sugar for dereferencing -- so your code accesses memory its not supposed to.
The first version of your code initializes the pointer to actually point to something, and hence when you dereference it during the loop, it works.
Of course, in either case, you return the pointer from the function -- its just that in the first version it points to something valid, whereas in the second version it points anywhere.
The moral here is to always initialize your variables. Not doing so could result in undefined behavior in your code (even if it appears to work sometimes). The general advice here is to always compile your code using at least some compilation flags. For example in gcc/clang, consider -Wall -Werror -Wextra. Such options often pick up on simple cases of not initializing variables.
Also, valgrind is a brilliant tool for memory profiling. It can easily detect uses of uninitialized memory at runtime, and also memory leaks.
Simple: because you do not have any allocated memory for the data you wite. In your example you define pointer, you do not initialize it so it will reference random (or rather not possible to predict) place in the memory, then you try to write to this random memory location.
You have 2 Undefined Behaviours here in 5 lines example. Your pointer is not initialized, and you did not allocate any valid memory this pointer to reference.
EDIT:
VALID
char *cstring(char c, int n)
{
char * res;
res = malloc ((n+1)*sizeof(char));
char *cstring(char c, int n)
{
char * res;
static char buff[somesize];
res = buff;
char buff[somesize];
char *cstring(char c, int n)
{
char * res;
res = buff;
INVALID
char *cstring(char c, int n)
{
char * res;
char buff[somesize];
res = buff;

Allocating and initialising a pointer in C

So, I am new to pointers to in C.
I am facing a confusion.
If I have,
int a;
Here, I dont allocate memory manually for a. It's done automatically by the compiler.
Now, if in a similar fashion, if I do,
char * a;
Do I need to allocate memory for the pointer?
Secondly, I made this code,
#include <stdio.h>
int main (void)
{
int *s=NULL;
*s=100;
printf("%d\n",*s);
return 0;
}
Why do I get a seg fault in this code? Is it because I havent allocated memory for the pointer? But as asked in the above question, I can simply declare it as well without manually allocating the memory.
PS: I am new to pointers and I am facing confusion in this. Spare me if it is a bad question. Thanks.
Edit: I read the post for malloc on SO.
http://stackoverflow.com/questions/1963780/when-should-i-use-malloc-in-c-and-when-dont-i
It doesnt really solve my doubt.
You don't need to allocate memory for the pointer itself. That's automatic, like the int in your first code snippet.
What you do need to allocate is the memory that the pointer should point to, and you need to initialize the pointer to point to that.
Since you're not allocating any space, the *s= assignment is undefined behavior. s itself (the pointer) is allocated, and initialized to NULL. You can't dereference (*s - look at what the pointer points to) a null pointer.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int *s = NULL; // s is created as a null pointer, doesn't point to any memory
s = malloc(sizeof(int)); // allocate one int's worth of memory
*s = 100; // store the int value 100 in that allocated memory
printf("%d\n",*s); // read the memory back
free(s); // release the memory
// (you can't dereference s after this without
// making it point to valid memory first)
return 0;
}
You have to allocate memory for the variable s you are declaring. Malloc is a nice way to do that. With int *s=NULL the pointer does not point to any address. And after that you trying to give a value to that address (*s=100;). If you do not want to allocate memory manualy (with malloc) you simply declare an int variable and then make s pointing to that variable.
With malloc:
#include <stdio.h> int main (void)
{
int *s=NULL;
s=(int *)malloc(sizeof(int));
*s=100;
printf("%d\n",*s);
return 0;
}
Without malloc:
#include <stdio.h>
int main (void)
{
int *s=NULL;
int var;
s=&var;
*s=100;
printf("%d\n",*s);//100
printf("%d\n",var);//also 100
return 0;
}
As pointers are also special type of variables which stores the address of other variables,As the address is also some value(number), Hence memory is also needed to store this address,so compiler automatically allocates memory(exactly 4 bytes on 32-bit machine) to a pointer variable,when you are allocating the memory using malloc() or calloc()your are actually allocating the memory to the data which is to be stored,and simply assigning the starting address of this memory to the pointer.
In your example at the line
int *s=NULL; //this line
Compiler actually allocates memory of 4 bytes (if your machine is 32-bit)
see this small snippet
int main(void)
{
int *s=NULL;
printf("%d\n",sizeof(s)); //Will output 4 if you are using is 32-bit OS or else 2 if you are using using 16 bit OS.
return 0;
}
And NULL is simply just another way of assigning Zero to a pointer.So technically your actually using 4 bytes to store zeros in that pointer. And don't be confused, assigning zero or NULL means that the pointer is not pointing to any data(as it doesn't hold a valid address,Zero is not valid address).

Pointer to struct containing array

I have a simple struct containing an array of ints and an index to be used for that array.
#define BUFF_SIZE 100
typedef struct _buffer Buffer;
struct _buffer {
int buff[BUFF_SIZE];
int index;
};
I am trying to write a function to create a pointer to an instance of this struct, and initialise its values to zero. However when I try to initialise the array using the arrow operator I get an error that the expression is invalid.
...
Buffer* newBuff;
newBuff->buff = {0}; //Error occurs here
...
I know that in c an array is a pointer to the base of the memory block in which the array resides, but was under the impression that dereferencing the struct pointer would allow me to access the array. Am I wrong about this, or am I missing something here? I have a feeling that it is something very simple, but for the life of me I just can't spot it.
Thanks!
EDIT: Thanks for the quick answers guys, they've helped me understand some of what is occurring. I neglected to mention that this is intended to be run on an embedded system (sorry about that), so I would like to avoid using includes or malloc if at all possible.
There are several types of confusion here. A pointer points to memory (duh), but you need to get that memory from somewhere. How you initialize that memory is separate.
You can allocate your structure on the stack by declaring a local variable inside your function:
// Initialize all buff elements and index to 0
// Note: Buffer, not Buffer*
Buffer newBuf = { {0}, 0 };
Or you can allocate it on the heap:
Buffer *newBuf = malloc(sizeof(Buffer));
memset(newBuf, 0, sizeof(Buffer));
When allocating objects on the stack, they are only valid while the current function is executing. You can't return a pointer to an object on the stack. Further, stack space is typically limited, so you can't put megabyte-sized objects there. When allocating memory on the heap with malloc(), you need to take care to free() when it is not used any more, otherwise you leak memory.
You see that when allocating objects on the stack, you are able to use an initializer-list { {0}, 0 }. In the heap case, you can not do that and you have to zero the memory manually using memset.
The problem is not with the arrow -> operator, it's with the right side of the assignment: {0} is allowed in initializers, but you cannot assign an array like that. You need to use memset to zero out the elements of the array:
memset(newBuff->buff, 0, sizeof(newBuff->buff));
Note: your code does not set the newBuf to a valid location in memory. You need to allocate memory first, like this:
newBuff->buff = malloc(sizeof(*newBuff));
I have to disagree with #dasblinkenlight, but I think the problem is that newBuff is a pointer, but it hasn't been given a value. Hence, when you dereference it, you'll probably get a crash or unpredictable results.
You'd have to have a statement that's something like:
newBuff = malloc(sizeof (Buffer));
to allocate space of the appropriate size and assign it to newBuff.
Unless I'm missing something terribly obvious...
From your question I was able to understand- you want to initialize all array elements of structure variable buff[ ] to zero.
memset() function from <string.h> file will help you to solve this problem.
As you said you are writing code for embedded system so there is no need to include whole <string.h> file in your program
I tried to replicate your program and found the following solution-
void *memset(void * , int , size_t ) __attribute__((__nonnull__(1)));
#define BUFF_SIZE 100
typedef struct _buffer Buffer;
struct _buffer {
int buff[BUFF_SIZE];
int index;
};
int main (void)
{
Buffer* newBuff;
memset(newBuff->buff, 0, BUFF_SIZE);
}
Please let me know if it was helpful.

When must I use malloc to allocate memory?

1)
For which datatypes must I allocate memory with malloc?
For types like structs, pointers, except basic datatypes, like int
For all types?
2)
Why can I run this code? Why does it not crash? I assumed that I need to allocate memory for the struct first.
#include <stdio.h>
#include <stdlib.h>
typedef unsigned int uint32;
typedef struct
{
int a;
uint32* b;
}
foo;
int main(int argc, char* argv[])
{
foo foo2;
foo2.a = 3;
foo2.b = (uint32*)malloc(sizeof(uint32));
*foo2.b = 123;
}
Wouldn't it be better to use
foo* foo2 = malloc(sizeof(foo));
3)
How is foo.b set? Does is reference random memory or NULL?
#include <stdio.h>
#include <stdlib.h>
typedef unsigned int uint32;
typedef struct
{
int a;
uint32* b;
}
foo;
int main(int argc, char* argv[])
{
foo foo2;
foo2.a = 3;
}
All types in C can be allocated either dynamically, automatically (on the stack) or statically. The issue is not the type, but the lifetime you want - you use malloc when you want an object to exist outside of the scope of the function that created it, or when you don't know in advance how big a thing you need.
Edit to address your numbered questions.
There are no data types you must allocate with malloc. Only if you want a pointer type to point to valid memory must you use the unary & (address-of) operator or malloc() or some related function.
There is nothing wrong with your code - the line:
foo foo2;
Allocates a structure on the stack - then everything works as normal. Structures are no different in this sense than any other variable. It's not better or worse to use automatic variables (stack allocation) or globals or malloc(), they're all different, with different semantics and different reasons to choose them.
In your example in #3, foo2.b's value is undefined. Any automatic variable has an undefined and indeterminate value until you explicitly initialize it.
You must allocate with malloc any memory that you wish to be managed manually, as opposed to automatically. It doesn't matter if what's stored there is an int or a double or a struct or anything; malloc is all about manual memory management.
When you create a variable without malloc, it is stored on the stack and when it falls out of scope, its memory is automatically reclaimed. A variable falls out of scope when the variable is no longer accessible; e.g. when the block or function that the variable was declared in ends.
When you allocate memory with malloc, it is stored on the heap, and malloc returns a pointer to this memory. This memory will not be reclaimed until you call free on it, regardless of whether or not a pointer to it remains accessible (when no pointers remain to heap-allocated memory, this is a memory leak). This means that you gain the ability to continue to use the memory you allocated after the block or function that it was allocated in ends, but on the other hand you now have the responsibility to manually deallocate it when you are finished with it.
In your example, foo2 is on the stack, and will be automatically deallocated when main ends. However, the memory pointed to by foo2.b will not be automatically deallocated, since it is on the heap. This isn't a problem in your example because all memory is returned to the OS when the program ends, but if it were in a function other than main it would have been a memory leak.
foo foo2; automatically allocates the structure on the stack, and it is automatically deallocated when the enclosing function (main in this case) ends.
You only need to allocate memory on the heap, using malloc, if you need the structure to persist after the enclosing scope ends. You may also need to do this when the object is too large to fit on the stack.
2) Why can I run this code? Why does it not crash?
The code never refers to undefined memory or NULL. Why would it crash? (You have a memory leak as written, but it's probably because you're only showing part of the code and in the given program it's not a problem anyway.)
The alternative code you suggest will also work, though memory returned from malloc is also uninitialized by default. (I once worked with a custom memory allocator that filled returned memory blocks with ? characters by default. Still perfectly legal by the rules. Note that calloc returns a pointer to zero-initialized memory; use it if that's what you want.)
3) How is foo.b set? Does is reference random memory or NULL?
Random memory. Stack allocated structures are not initialized for you.
You can do it, but this is not enough.
Because, the second field is a pointer, which has to be set to a valid address. One of the ways to do it is by allocating memory (with malloc).
To your first question -
use malloc when you MUST manage object's lifetime manually.
For instance, the second code could be rewritten as:
int main(int argc, char* argv[])
{
foo foo2; uint32 b;
foo2.a = 3;
foo2.b = &b;
*foo2.b = 123;
}
This is better, because lifetime is the same, and the memory is now on stack - and doesn't need to be freed.
The memory for the struct instance ("foo2") will be allocated on the stack - there's no need to allocate memory for this yourself - if you do allocate using malloc be sure to free off the memory at a later date.

Resources