Realloc a table of structures that has table in it - c

I am trying to write a programe that will store data in a table of structures. My problem is that i can't figure out why my realloc isn't working.
I am trying to realloc a table that is in a table of structures (sounds confusing, i know), but it won't work. Here is the part of my program i have a problem with:
typedef struct {
int *node;
int l;
}przejscie_t;
void czytaj(przejscie_t **graf, int vp, int vk){
*graf=realloc(*graf,(vp+1)*sizeof(przejscie_t));
(*graf)[vp].l=1;
(*graf)[vp].node=realloc((*graf)[vp].node,(*graf)[vp].l*sizeof(int)); //it crashes here
(*graf)[vp].node[(*graf)[vp].l]=vk;
}

(*graf)[vp].node=realloc((*graf)[vp].node,(*graf)[vp].l*sizeof(int)); //it crashes here
realloc needs a valid initialized pointer as first parameter (or NULL, in this case it stands as if malloc was called), since (*graf)[vp].node is not initialized you are passing garbage.

If your struct was initialized with calloc() OR set to zero with memset() (or manually) OR (*graf)[vp].node was set to null, realloc() would actually acted like malloc() for the required size.
If ptr is a null pointer, realloc() behaves like malloc() for the specified size.
However, if you did not set your structure's memory or node pointer to zero when initializing the structure, you are probably passing garbage to your realloc, which gives access to unwanted memory and can cause many problems.
I can only strongly advise you to always initialize your tables/structures to zero before doing anything with them.
Fun fact:
realloc() would act like free() if size is set to 0 and ptr is not null.
Source : Relatively any realloc() manual you can find that respect the common standards.

Related

do I need to allocate space for pointer as well as space for memory area whose address will be kept in pointer in pointer to pointer and realloc

I have this code
int main(int argc, char *argv[])
{
int i=1;
char **m=malloc(sizeof(char *)*i);
printf("%zu\n",sizeof *m);
m[0]=malloc(strlen("hello")+1);
strcpy(m[0],"hello");
printf("%s\n", m[0]);
i=2;
m=(char **)realloc(m,sizeof (char *)*i);
m[1]=malloc(strlen("hi")+1);
strcpy(m[1],"hi");
printf("%s %s \n",m[0],m[1] );
// TODO: write proper cleanup code just for good habits.
return 0;
}
this is how I am allocating pointer char **m 8 byte single char pointer
int i=1;
char **m=malloc(sizeof(char *)*i);
and this is how I am allocating area of space whose address will be kept in m[0]
m[0]=malloc(strlen("hello")+1);
strcpy(m[0],"hello");
printf("%s\n", m[0]);
I like to know is this normally how its done. I mean allocating space for pointer and then allocating space in memory that the pointer will hold.
Does m[0]=malloc(strlen("hello")+1); is same as this *(m+0)=malloc(strlen("hello")+1); and does this m[1]=malloc(strlen("hi")+1); this *(m+1)=malloc(strlen("hi")+1);
And I am increasing pointer to pointer numbers like this in allocation m=(char **)realloc(m,sizeof (char *)*i); before m[1]=malloc(strlen("hi")+1);
is there anything wrong with above code. I seen similar code on this Dynamic memory/realloc string array
can anyone please explain with this statement char **m=malloc(sizeof(char *)*i); I am allocating 8 byte single pointer of type char but with this statement m=(char **)realloc(m,sizeof (char *)*i); why I am not getting stack smaching detected error. How exactly realloc works. can anyone give me the link of realloc function or explain a bit on this please
I like to know is this normally how its done. I mean allocating space for pointer and then allocating space in memory that the pointer will hold.
It depends on what you are trying to achieve. If you wish to allocate an unspecified amount of strings with individual lengths, then your code is pretty much the correct way to do it.
If you wish to have a fixed amount of strings with individual lengths, you could just do char* arr [n]; and then only malloc each arr[i].
Or if you wish to have a fixed amount of strings with a fixed maximum length, you could use a 2D array of characters, char arr [x][y];, and no malloc at all.
Does m[0]=malloc(strlen("hello")+1); is same as this *(m+0)=malloc(strlen("hello")+1);
Yes, m[0] is 100% equivalent to *((m)+(0)). See Do pointers support "array style indexing"?
is there anything wrong with above code
Not really, except stylistic and performance issues. It could optionally be rewritten like this:
char** m = malloc(sizeof(*m) * i); // subjective style change
m[0]=malloc(sizeof("hello")); // compile-time calculation, better performance
why I am not getting stack smaching detected error
Why would you get that? The only thing stored on the stack here is the char** itself. The rest is stored on the heap.
How exactly realloc works. can anyone give me the link of realloc function or explain a bit on this please
It works pretty much as you've used it, though pedantically you should not store the result in the same pointer as the one passed, in case realloc fails and you wish to continue using the old data. That's a very minor remark though, since in case realloc fails, it either means that you made an unrealistic request for memory, or that the RAM on your system is toast and you will unlikely be able to continue execution anyway.
The canonical documentation for realloc would be the C standard C17 7.22.3.5:
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
The realloc function deallocates the old object pointed to by ptr and returns a
pointer to a new object that has the size specified by size. The contents of the new
object shall be the same as that of the old object prior to deallocation, up to the lesser of
the new and old sizes. Any bytes in the new object beyond the size of the old object have
indeterminate values.
If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined. If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
Returns
The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object could not be allocated.
Notably there is no guarantee that the returned pointer always has the same value as the old pointer, so correct use would be:
char* tmp = realloc(arr, size);
if(tmp == NULL)
{
/* error handling */
}
arr = tmp;
(Where tmp has the same type as arr.)
Your code looks fine to me. Yes, if you are storing an array of strings, and you don't know how many strings will be in the array in advance, then it is perfectly fine to allocate space for an array of pointers with malloc. You also need to somehow get memory for the strings themselves, and it is perfectly fine for each string to be allocated with its own malloc call.
The line you wrote to use realloc is fine; it expands the memory area you've allocated for pointers so that it now has the capacity to hold 2 pointers, instead of just 1. When the realloc function does this, it might need to move the memory allocation to a different address, so that is why you have to overwrite m as you did. There is no stack smashing going on here. Also, please note that pointers are not 8 bytes on every platform; that's why it was wise of you to write sizeof(char *) instead of 8.
To find more documentation about realloc, you can look in the C++ standard, or the POSIX standard, but perhaps the most appropriate place for this question is the C standard, which documents realloc on page 314.

is this use of realloc inside a function correct? (and the use of free() in case of failure)

I found some questions similar to this but there are some differences.
here is my code:
student.h:
#define NUM_GRADES 5
#define NAME_LENGTH 21
#define ADDRESS_LENGTH 21
typedef struct
{
char name[NAME_LENGTH]; //name of a student - up to 20 chars.
char add[ADDRESS_LENGTH]; //address - up to 20 chars.
int grades[NUM_GRADES]; //stores the grades of a student.
}student;
//the current size of the students array.
extern int currentTotal;
//add a new student space, return 0 if failed, 1 if succeeded.
int addStudent(student **studentClass);
student.c:
int addStudent(student **studentClass)
{
//adds the count for the new student.
currentTotal++;
//a temporary pointer to hold studentClass array in case realloc fails.
student *temp=NULL;
//reallocating space for the new student.
if (!(temp = (student*)realloc(*studentClass, currentTotal * sizeof(student))))
{
printf("Not enough memory.\n");
free(*studentClass);//free the original array.
currentTotal = 0;
return 0;
}
*studentClass = temp;//point class to the newly allocated space.
printf("Added space for a student.\n");
return 1;
}
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "student.h"
void main()
{
student *studentClass=NULL;
....
if(addStudent(&studentClass)
....
currentTotal is an external int variable.
Is the use of realloc correct?
And the use of free?
I always mix up whether I should use * or ** inside the function, once I send the address of a pointer to another function. (i.e. having a pointer like *studentClass and then sending &studentClass to another function).
if this is indeed correct then what happens to the original data that *studentClass pointed before the line
"*studentClass = temp;" (in student.c) ?
does it need to be freed?
edit:
Please don't be confused that initially *studentClass is NULL, it's only like that at the start, addStudent() is meant to be called in a loop, so after the first time, *studentClass is no longer NULL. addStudent() increase the size of *studentClass after each call.
Thanks.
It's "save" in the sense that it does not introduce undefined behaviour and it does not leak memory. You take care that if realloc fails, the original data is not freed (so you do it), and you store the result of realloc in a temp variable in order not to loose the pointer to the original data. So far everything is OK.
It contains, however, a pitfall for the caller of addStudent if realloc fails. In this case, you free the original memory block without providing a new one, but you do not reset the pointer to NULL. So the variable passed to addStudent still points to some memory, but this memory has been freed. A caller might attempt to free this memory a second time (yielding undefined behaviour then).
In case of realloc having failed, I'd suggest to do either of two options depending on who shall be responsible for freeing student's array memory:
a. addStudent is responsible: Free the original memory AND set the pointer to NULL, such that no one outside can attempt to free memory twice. So you'd add a *studentClass=NULL after the free.
b. the caller is responsible: Don't free original memory in case of realloc failure; return - as you do - a failure code and let the caller do the rest. So you'd remove the free.
This is all fine. Because *studentClass is NULL, realloc(3) behaves just like malloc(3). In the case that realloc(3) fails, it does not modify the passed pointer, meaning that *studentClass is still NULL. Calling free(3) on a NULL pointer is perfectly valid, but nothing will happen (a no-op). Then the function returns, and *studentClass is still NULL. You just need to check its value after the call to addStudent: if it's NULL the addition of a student failed, otherwise it succeeded.
Your use of double-pointers is also valid. One way to reason about this is like so. Pointers allow modification of the data at the pointed-to location. If one wants to pass an integer to a function to be modified, one can pass it as an int*. Inside the function, one dereferences it to modify it, such as *my_int = 0;. So if one wants to modify a student* inside a function, it must be passed as a student** and then dereferenced whenever one wants to change its contents.
In addition to the fact mentioned by Stephan Lechner that code should either leave the allocation alone or null out the pointer to it (as opposed to freeing the memory without nulling out the pointer) there are a couple of other issues I see:
If a caller isn't expected to recover from out-of-memory conditions, allocation functions shouldn't return when they occur. Instead they should signal the fault (perhaps by raising a signal) and then exit (if signalling the fault didn't already force an exit). Having a function guarantee that it will never return unsuccessfully can greatly simplify client code.
If the function is going to use a global variable to hold the size of the allocation, it should use a global pointer to the allocation. If it is going to use an object-pointer identified by a passed-in address, it should use an object count that is also identified by a passed-in address.
I can see four good approaches to fixing that second issue:
Pass in a double-indirect pointer as you do now, but also pass a pointer to an integer-type object holding the number of students.
Pass in a pointer to a structure which holds a student pointer and the number of students.
Define a structure which holds a count and a flexible array member of the student type, and keep a pointer to that rather than to the first student.
As above, but keep a pointer to the first student (as opposed to the start of the allocated region). This would require that any code that uses malloc/realloc/free be adjusted to offset the pointers exchanged with such functions.
Approaches #3 and #4 could have a slight advantage if the number of students can grow instead of shrink. If the size of the allocated region shrinks to zero, there would be no way to determine whether a request to realloc a region's size to zero bytes succeeds (if the region previously had a zero size, the Standard would allow realloc(prevPtr,0) to return null after having successfully released the previous allocation, but the Standard would also allow the realloc to fail (and return null) without having released the previous allocation.

Freeing dynamically allocated int that needs to be returned but cannot be freed in main in c

As my long title says: I am trying to return a pointer in c that has been dynamically allocated, I know, I have to free it, but I do not know how to myself, my search has showed that it can only be freed in main, but I cannot leave it up to the user to free the int.
My code looks like this right now,
int *toInt(BigInt *p)
{
int *integer = NULL;
integer = calloc(1, sizeof(int));
// do some stuff here to make integer become an int from a passed
// struct array of integers
return integer;
}
I've tried just making a temp variable and seeing the integer to that then freeing integer and returning the temp, but that hasn't worked. There must be a way to do this without freeing in main?
Program design-wise, you should always let the "module" (translation unit) that did the allocation be responsible for freeing the memory. Expecting some other module or the caller to free() memory is indeed bad design.
Unfortunately C does not have constructors/destructors (nor "RAII"), so this has to be handled with a separate function call. Conceptually you should design the program like this:
#include "my_type.h"
int main()
{
my_type* mt = my_type_alloc();
...
my_type_free(mt);
}
As for your specific case, there is no need for dynamic allocation. Simply leave allocation to the caller instead, and use a dedicated error type for reporting errors:
err_t toInt (const BigInt* p, int* integer)
{
if(bad_things())
return ERROR;
*integer = p->stuff();
return OK;
}
Where err_t is some custom error-handling type (likely enum).
Your particular code gains nothing useful from dynamic allocation, as #unwind already observed. You can save yourself considerable trouble by just avoiding it.
In a more general sense, you should imagine that with each block of allocated memory is associated an implicit obligation to free. There is no physical or electronic representation of that obligation, but you can imagine it as a virtual chit associated at any given time with at most one copy of the pointer to the space during the lifetime of the allocation. You can transfer the obligation between copies of the pointer value at will. If the pointer value with the obligation is ever lost through going out of scope or being modified then you have a leak, at least in principle; if you free the space via a copy of the pointer that does not at that time hold the obligation to free, then you have a (possibly virtual) double free.
I know I have to free it, but I do not know how to myself
A function that allocates memory and returns a copy of the pointer to it without making any other copies, such as your example, should be assumed to associate the obligation to free with the returned pointer value. It cannot free the allocated space itself, because that space must remain allocated after the function returns (else the returned pointer is worse than useless). If the obligation to free were not transferred to the returned pointer then a (virtual) memory leak would occur when the function's local variables go out of scope at its end, leaving no extant copy of the pointer having obligation to free.
I cannot leave it up to the user to free the int.
If you mean you cannot leave it up to the caller, then you are mistaken. Of course you can leave it up to the caller. If in fact the function allocates space and returns a pointer to it as you describe, then it must transfer the obligation to free to the caller along with the returned copy of the pointer to the allocated space. That's exactly what the calloc() function does in the first place. Other functions do similar, such as POSIX's strdup().
Because there is no physical or electronic representation of obligation to free, it is essential that your functions document any such obligations placed on the caller.
Just stop treating it as a pointer, there's no need for a single int.
Return it directly, and there will be no memory management issues since it's automatically allocated:
int toInt(const BigInt *p)
{
int x;
x = do some stuff;
return x;
}
The caller can just do
const int my_x = toInt(myBigInt);
and my_x will be automatically cleaned away when it does out of scope.

free(struct variable) doesn't clear previous stored values associated with that variable when I malloc again?

I created a struct like the following:
typedef struct header{
int hc;
char src[18];
char dst=[18];
char reason[15];
char d[3];
char m[3];
char y[4];
struct measurements{
char h_ip[17];
int h_ttl;
int h_id;
float h_rtt;
}HOPS[100];
}HEADER;
INSIDE MAIN:
HEADER *head;
for(...){
head=(HEADER*) malloc(sizeof(HEADER));
.....
free(head);
}
Will the above malloc automatically allocate memory for the inner struct as well? Also, I'm facing a weird problem here. After I free the header, I'm still able to print the values of head->HOPS[i].h_ip. Should I explicitly free the inner struct as well so that even the values get cleared?
Yes, it allocates memory for the inner structure. And you need not free the inner structure separately.
If you have a pointer defined inside your structure, in that case you have to allocate separately for that pointer member of the structure and free that separately.
Consider freeing memory as a black box. All what you know is that after freeing you shouldn't refer to freed memory.
You may find that that memory block still exists and still contains some old values. That's ok: it just was marked as freed and probably it will be used again soon by allocator.
For example when you call malloc again and realized that just allocated block contains values from the old structure. It happens and that's alright. Just use this block as usually.
So, after the problem with the wrong declaration of head was resolved:
free returns a previously allocated memory block to the heap. It does not clear anything (for performance reasons). However, you are not supposed to access that block anymore afterwards. Doing so results in undefined behaviour and might let your computer fly out of the window.
Worst that can happen is ... nothing ... Yes, you might even not notice anything strang happens. However, that does not mean your program run correctly, it just does not show any symptoms.
To catch illegal accesses, you might set the pointer to NULL once you freed the object it points to. Some operating systems catch accesses to addresses near the null pointer address, but there is no guarantee. It is a good practice anyway and does no harm.
For your other question: malloc allocates a block of memory large enough to store that many bytes you passed as argument. If it cannot, it will return a null pointer. You should always check if malloc & friends returned a valid pointer (i.e. not a null pointer).
int *p = malloc(sizeof(int));
if ( p == NULL ) {
error: out of memory
}
...
Notice the omission of the cast of the result of malloc. In C you should not cast void * as returned by malloc & friends (but also elsewhere). As much as you did not for free(head). Both take the same type: void *, btw. (so why cast one and not the other?). Note that in C any object pointer can freely be assigned to/from void * without cast. Warning functions are no objects in the C standard!
Finally: sizeof(HEADER) returns the size of the struct. Of course that include all fields. A nested struct is a field. A pointer to another struct is a field. For the latter, however note: the pointer itself is a field, but not what it points to! If that was another struct, you have to malloc that seperately **and also free seperately (remember what I wrote above).
But as you do not have pointer inside your struct, that is not your problem here. (keep it in mind, if you continue programming, you will eventually need that!)

Calloc(), Structs & C

So I'm new to C and creating some simple programs to help me get a hang of things.
Let's say I have a struct as follows:
typedef struct {
char* field;
} something;
And I dynamically allocate space for 10 of these as follows:
something* stuff = calloc(10, sizeof(something));
Let's say I then want to delete one of these somethings. Would it make sense to do:
free(&stuff[4]);
Or would that only make sense if I had made all of these pointers to somethings instead of a contiguous block of somethings?
If I did that and it worked, would:
stuff[4] = malloc(sizeof(something))
Then be all I need to re-add a "something" to that index?
Or, in general, do we usually deal with such structures as a block of memory that contains pointers to the structs, not the structs themselves?
Thanks.
The rule is very simple. You can and should free precisely that which you allocated. That is, you must only pass pointers to free() which you received as the return value of malloc/calloc/realloc etc.*, or a null pointer. Nothing else may be passed to free().
So, you can free tne entire array, or nothing at all.
(Note also that "freeing a single element from the middle" would be utterly pointless, because you would have no way of iterating over such a "holy" array sensibly.) If you want to deallocate some memory, allocate a new range, copy the desired elements over and free the original array.
*) Some quasi-standard functions may indirectly return dynamically allocated memory which you must fre; check the documentation. Some examples are strdup, GNU's scanf, and GCC's abi::__cxa_demangle.)
According to the man pages
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs.
You can only free the whole block of data. So do not attempt to free anything else.

Resources