Allocating memory for structs, 2 different ways? - c

I am new in C, but not new in programming. Is there a difference between the 2 sets of codes ? If there is not, is there a convention on which one to prefer ? Is there a performance difference ?
typedef struct
{
int x;
int y;
} something_t;
-
something_t* s;
s = malloc(sizeof(int)*2);
s->x = 1;
s->y = 1;
or
something_t* s;
s->x = 1;
s->y = 1;

The good way to do it is
something_t *something;
something = malloc(sizeof(*something));
if (something == NULL)
please_do_not_use_something_perhaps_return_NULL_or_quit();
something->x = 2;
something->y = 2;
This way, you ensure the size is right and the code is more maintainable. And you also prevent a disaster by checking that malloc() didn't return NULL giving you chance to do something about it. Assuming no-errors is wrong all the time, in this because you never know when the system will run out of RAM.
Your second example doesn't work, this
something_t *something;
something->x = 2;
something->y = 2;
Invokes Undefined Behavior, one of the possible outcomes is that it "Works". So you might think that it worked because of undefined behavior, but the truth is, it's wrong.
In this case something doesn't point to valid memory, so you don't know for sure what the value of something is and it can be anything, thus the behavior of such program is unpredictable.
Also, read why you should avoid _t as a suffix for type names.

To my understanding, the first version should be
something_t* s;
s = malloc(sizeof(something_t));
s->x = 1;
s->y = 1;
instead of manually fiddling with the size of individual members; the second versions performs no allocation at all and accesses uninitialized memory.

something_t* s;
does not allocate any memory for your structure, it only allocates a pointer (to a random memory area). It is very likely it will trigger a segmentation fault when you try to read/write to it.
The good way to allocate your memory is
something_t* s;
s = malloc(sizeof(something_t));
or the one-liner
something_t* s = malloc(sizeof(something_t));
Don't forget to use free(s); when you're done with it.
If you want stack-allocation, you can use :
something_t s;
s.x = 2;
s.y = 2;

Related

Valgrind + C: Handling uninitialized pointers without error

Maybe I got too involved with testing my assignment, but here's my dilemma:
This is my offending function (more or less):
struct thing{
char* data;
}
int function(struct thing* arg){
if(arg->data == NULL)
return -1;
}
This is my offending input:
struct thing *x = malloc(sizeof(struct thing));
function(x);
And valgrind outputs this when I test it:
Conditional jump or move depends on uninitialised value(s)
I'm about 99% sure that this is because valgrind has an issue with evaluating x->data when it hasn't been initialized to NULL or malloced. Is there a workaround for this?
To my opinion valgrind is right in complaining here because data is in fact not initialized and function is not able to determine if it was. The function can only check if it has the defined value you used for initialization.
So I would consider using a creation function that does the initialization as well. This way you could also allocate the memory for data right away when passing its size as parameter (or just NULL if you want to do that later).
struct thing *newThing(size_t dataSize)
{
struct thing *t = malloc(sizeof (struct thing));
if (t)
t->data = malloc(sizeof(char) * dataSize);
// or t->data = NULL if it should be done later
return t;
}
You are defining a function like this:
int function(struct thing *arg) {
if (arg->data == NULL) {
// abort here
return 1;
} else {
// use the value here
return 0;
}
}
Here, Valgrind is right about complaining, because it's impossible to achieve the intended behavior for function(). If arg->data is not explicitly initialized, then its value is indeterminate, and the if statement could execute any of the two branches depending on whichever random value it reads from arg->data.
In general, it's impossible for the function to work correctly, because:
If the check arg->data == NULL fails, the rest of the code will assume that arg->data is not NULL and therefore use the invalid value, most likely causing a crash or other kind of problem.
If the check arg->data == NULL passes, the rest of the code will wrongfully assume that the data is known to be invalid, and do any other kind of thing assuming that data was intended to be NULL, like for example call some cleanup code at the wrong time.
Other than this, if you really want to be pedantic, reading uninitialized variables is actually undefined behavior in C.
The right thing to do in your case is to either use calloc() instead of malloc() or to manually set x->data = NULL right after malloc().
The memory allocated by malloc is not initialized.
You need to set it to the know state:
struct thing *x = calloc(1,sizeof(*x));
or
struct thing *x = malloc(sizeof(*x));
memset(x, 0, sizeof(*x);
you can also of course just assign some values to the struct members,
struct thing *x = malloc(sizeof(*x));
x -> data = NULL;

Realloc doesn't seem to enlarge array

so I have to write something like garbage collector for school project in C. I am stuck at problem with dynamic memory allocation. My function growActivePtrs() should enlarge global array of structs by one, but it does not seem to be working. I have read a ton on materials on dynamic allocation and tried many things, but I just cant find the mistake.
typedef struct activePtr
{
// pointer to actively used memory
void *memPointer;
// number of times this memory is referenced
int timesUsed;
} activePtr;
activePtr **activePointers;
size_t *ptrCount = 0;
bool growActivePtrs()
{
const size_t totalSize = *ptrCount + 1;
activePtr *temp = (activePtr *)realloc(*activePointers, (totalSize * sizeof(activePtr)));
if (temp == NULL) {
return false;
}
*activePointers = temp;
*ptrCount += 1;
activePointers[*ptrCount - 1]->timesUsed = 0;
activePointers[*ptrCount - 1]->memPointer = NULL;
return true;
}
Any help will be much appreciated. Thank you.
size_t *ptrCount = 0;
This defines ptrCount as a pointer to size_t, initialised to a null pointer. Unless you assign it the location of some actual size_t object (and it looks like you haven't), any attempt to access *ptrCount is doomed to fail.
There is no reason why this should be a pointer. You can just store a size_t directly.
As #user3121023 rightly points out in a comment, the same applies to your activePointers variable.

Realloc Causes Heap Corruption

I am trying to write a code in C where I am facing an issue with the realloc. The code works fine at some point of time, but crashes with a Heap Corruption error during the realloc at another time.
I have pasted the structures and the function that populates the data into it. Could anyone please tell me if I am doing something wrong here.
typedef struct MyDataStructureStr
{
MyDataStructureStr()
{
val1 = -1;
val2 = -1;
}
int val1;
int val2;
} MyDataStructureStr, *MyDataStructurePtr;
typedef struct MyStructureStr
{
MyStructureStr()
{
connector = NULL;
counter = 0;
}
MyDataStructurePtr connector;
int counter;
}MyStructureStr, *MyStructurePtr;
static void storeData(int first, int second)
{
if(myStruct->connector == 0)
myStruct->connector = (MyDataStructurePtr)malloc(sizeof(MyDataStructureStr);
else
myStruct->connector = (MyDataStructurePtr)realloc(myStruct->connector, sizeof(MyDataStructureStr) * (myStruct->counter + 1));
myStruct->connector[myStruct->counter].val1 = first;
myStruct->connector[myStruct->counter].val2 = second;
myStruct->counter++;
}
Any suggestions are welcome.
Thanks in advance
A few points.
You do not need do the if(myStruct->connector == 0) thing. realloc will allocate memory if passed a NULL pointer. Per the man page: If ptr is NULL, then the call is equivalent to malloc(size), for all values of size'.
Your typedef struct functions are legal, but you should note they aren't being called.
I can't see where counter is being initialized to zero or connector to NULL. This may be because you haven't pasted the whole program.
I think the actual problem is that you are allocating counter data structures of sizeof(MyStructureStr). This should be sizeof(MyDataStructureStr) if I understand what you are doing. This may be the cause of the heap corruption but without a full program it's hard to tell.
Something else in the program (that you haven't pasted) may be corrupting the heap.
valgrind is the best way to debug this sort of problem

Dangling pointers and double free

After some painful experiences, I understand the problem of dangling pointers and double free. I am seeking proper solutions.
aStruct has a number of fields including other arrays.
aStruct *A = NULL, *B = NULL;
A = (aStruct*) calloc(1, sizeof(sStruct));
B = A;
free_aStruct(A);
...
// Bunch of other code in various places.
...
free_aStruct(B);
Is there any way to write free_aStruct(X) so that free_aStruct(B) exits gracefully?
void free_aStruct(aStruct *X) {
if (X ! = NULL) {
if (X->a != NULL) { free(X->a); x->a = NULL; }
free(X); X = NULL;
}
}
Doing the above only sets A = NULL when free_aStruct(A); is called. B is now dangling.
How can this situation be avoided / remedied? Is reference counting the only viable solution? Or, are there other "defensive" approaches to freeing memory, to prevent free_aStruct(B); from exploding?
In plain C, the most important solution to this problem is discipline, because the root of the problem is here:
B = A;
Making a copy of the pointer without changing anything within your struct, circumventing whatever you use without any warning from the compiler. You have to use something like this:
B = getref_aStruct(A);
The next important thing is to keep track of the allocations. Some things that help are clean modularization, information hiding and DRY -- Don't Repeat Yourself. You directly call calloc() to allocate the memory while you use a free_aStruct() function to free it. Better use a create_aStruct() to allocate it. This keeps things centralized and in one place only, instead of throwing memory allocations all over your codebase.
This is a much better base for whatever memory tracking system you build on top of this.
I do not think you can do this automatically as C places the onus and burden of you to manage the memory and therefore your responsibility to ensure that references and of course dangling pointers are looked after!
void free_aStruct(aStruct *X){
if (X ! = NULL){
if (X->a != NULL){free(X->a); x->a = NULL;}
free(X); X = NULL;
}
}
By the way, there's a typo blip in the if check above ... use of lower case 'x' instead of 'X'...
My thinking when I was looking at the above code is that you are doing a free on a copy of a pointer variable of type aStruct *. I would modify it to be a call-by-reference instead...
void free_aStruct(aStruct **X){
if (*X ! = NULL){
if (*X->a != NULL){
free(*X->a);
*X->a = NULL;
}
free(*X);
*X = NULL;
}
}
And call it like this:
free_aStruct(&A);
Other than that, you are ultimately responsible for the 'dangling pointers' yourself whether its an unintentional coding or a design fault...
Even if you could prevent the free_aStruct(B) from blowing up, if there's any reference to B in the code behind your comment, that's going to be using memory that's been freed, and so might be overwritten with new data at any point. Just "fixing" the free call will only mask the underlying error.
There are techniques you can use but the bottom line is that nothing you do can be strictly enforcable in C. Instead, i recommend incorporating valgrind (or purify) in your development process. Also, some static code analyzers may be able to detect some of these problems.
Reference counting's really not that hard:
aStruct *astruct_getref(aStruct *m)
{
m->refs++;
return m;
}
aStruct *astruct_new(void)
{
sStruct *new = calloc(1, sizeof *new);
return astruct_getref(new);
}
void astruct_free(aStruct *m)
{
if (--m->refs == 0)
free(m);
}
(In a multithreaded environment you will also potentially need to add locking).
Then your code would be:
aStruct *A = NULL, *B = NULL;
A = astruct_new();
B = astruct_getref(A);
astruct_free(A);
...
//bunch of other code in various places.
...
astruct_free(B);
You've asked about locking. Unfortunately there's no one-size-fits-all answer when it comes to locking - it all depends on what access patterns you have in your application. There's no substitute for careful design and deep thoughts. (For example, if you can guarantee that no thread will be calling astruct_getref() or astruct_free() on another thread's aStruct, then the reference count doesn't need to be protected at all - the simple implementation above will suffice).
That said, the above primitives can easily be extended to support concurrent access to the astruct_getref() and astruct_free() functions:
aStruct *astruct_getref(aStruct *m)
{
mutex_lock(m->reflock);
m->refs++;
mutex_unlock(m->reflock);
return m;
}
aStruct *astruct_new(void)
{
sStruct *new = calloc(1, sizeof *new);
mutex_init(new->reflock);
return astruct_getref(new);
}
void astruct_free(aStruct *m)
{
int refs;
mutex_lock(m->reflock);
refs = --m->refs;
mutex_unlock(m->reflock);
if (refs == 0)
free(m);
}
...but note that any variables containing the pointers to the structs that are subject to concurrent access will need their own locking too (for example, if you have a global aStruct *foo that is concurrently accessed, it will need an accompanying foo_lock).

What's the difference between intializating a struct as pointer or not?

I have the following for my HashTable structure:
typedef char *HashKey;
typedef int HashValue;
typedef struct sHashElement {
HashKey key;
HashValue value;
} HashElement;
typedef struct sHashTable {
HashElement *items;
float loadFactor;
} HashTable;
I never really thought about it until now but I just realized there's two ways how I can use this:
Alternative 1:
void hashInitialize(HashTable *table, int tabSize) {
table->items = malloc(sizeof(HashElement) * tabSize);
if(!table->items) {
perror("malloc");
exit(1);
}
table->items[0].key = "AAA";
table->items[0].value = 45;
table->items[1].key = "BBB";
table->items[1].value = 82;
table->loadFactor = (float)2 / tabSize;
}
int main(void) {
HashTable t1;
int i;
hashInitialize(&t1, HASHSIZE);
for(i = 0; i < HASHSIZE - 1; i++) {
printf("PAIR(%d): %s, %d\n", i+1, t1.items[i].key, t1.items[i].value);
}
printf("LOAD FACTOR: %.2f\n", t1.loadFactor);
return 0;
}
Alternative 2:
void hashInitialize(HashTable **table, int tabSize) {
*table = malloc(sizeof(HashTable));
if(!*table) {
perror("malloc");
exit(1);
}
(*table)->items = malloc(sizeof(HashElement) * tabSize);
if(!(*table)->items) {
perror("malloc");
exit(1);
}
(*table)->items[0].key = "AAA";
(*table)->items[0].value = 45;
(*table)->items[1].key = "BBB";
(*table)->items[1].value = 82;
(*table)->loadFactor = (float)2 / tabSize;
}
int main(void) {
HashTable *t1 = NULL;
int i;
hashInitialize(&t1, HASHSIZE);
for(i = 0; i < HASHSIZE - 1; i++) {
printf("PAIR(%d): %s, %d\n", i+1, t1->items[i].key, t1->items[i].value);
}
printf("LOAD FACTOR: %.2f\n", t1->loadFactor);
return 0;
}
Question 1: They both seem to produce the same result. On main, both examples print the right key/value pair. So, what exactly is the different between them besides the syntax change (using (*table) instead of just table), the extra code to allocate memory for the HashTable structure and the declaration of HashTable pointer?
I've been writing a few data structures lately like stacks, linked lists, binary search trees and now hash tables. And for all of them, I've always used the alternative 2. But now I'm thinking if I could have used alternative 1 and simplify the code, removing most of the * and & that are all over the place.
But I'm asking this question to understand the differences between the two methods and if, and also why, I should use on over the other.
Question 2: As you can see in the structures code, HashKey is a pointer. However, I'm not using strdup nor malloc to allocate space for that string. How and why is this working? Is this OK to do? I've always used malloc or strdup where appropriate when handling dynamic strings or I would get lots of segmentation faults. But this code is not giving me any segmentation faults and I don't understand why and if I should do it like this.
First both solutions are perfectly right !
Alternative 1 :
Your HashTable is declared in the main, which means the struct is somewhere in the call stack. The struct will be destroy if you leave the scope. Note : In your case that can't happen because the declaration is in the main so the scope ends on process exit.
Alternative 2:
You've got a HashTable* (pointer) in the call stack so you need to allocate the memory for the struct. To do so you use malloc.
In both case your struct is correctly allocated. The main difference will be on performances. It's far more performant to allocate on the stack but you can't do dynamic allocation. To do so you need to use malloc.
So, some times, you have to use malloc but try to avoid mallocing a lot if you want to do a high performance application.
Is that clear enough? :)
In alternative 1, the caller would allocate table but your function would allocate the contents thereof, which is not always a good idea in terms of memory management. Alternative 2 keeps all allocations in the same place.
As answered previously, the differences between the two alternatives is memory management. In alternative 1 you expect the caller to allocate the memory for table prior to the call; whereas, in alternative 2 just a pointer declaration is required to give you a place to put the memory after you've created it.
To question 2, the simple answer is that you are assigning a constant to the string. According to the following site the assignment is set up at compile time, not runtime.
http://publications.gbdirect.co.uk/c_book/chapter6/initialization.html
for question 2:
(*table)->items[0].key = "AAA";
actually puts "AAA" in read only parts of memory and char *key points to it, contents pointed by key cannot be changed.
(*table)->items[0].key[0]='a' gives and error
Here you can find further discussion about it.
What is the difference between char s[] and char *s?
The only difference is where the memory comes from -- local variables are typically on the stack whereas mallocs typically come from the heap.

Resources