C - allocating values in an array of pointers in outside function - c

Lets say I have the following situation (some rough pseudocode):
struct {
int i;
} x
main(){
x** array = malloc(size of x pointer); // pointer to an array of pointers of type x
int* size = current size of x // (initally 0)
add(array, size);
}
add(x** array, int* size){ // adds one actual element to the array
x** temp = realloc(array, (*size)+1); // increase the array size by one
free(array);
array = temp;
// My question is targeted here
array[*size] = malloc(size of x); // makes a pointer to the value
array[*size]->i = size;
*size++;
}
My question is: Once add() is finished, do the values of the pointers stored in array disappear along with the function call stack, since I allocated them inside func()? I fear that they might, in which case would there be a better way for me to do things?

No, they don't. They persist until the pointer returned by malloc() is passed to the corresponding free() function. There would be no point in the existence of the malloc() function if it worked the same way as automatic arrays.
Edit: sidenote. As #Ancurio pointer it out, you're incorrectly freeing the memory behind the previous pointer returned by malloc() which is at that time invalid as realloc() has been used on it. Don't do that. realloc() does its job properly.)

Related

Memory allocation using for loop

My Doubt is regarding only memory allocation so don't think about program output
#include<stdio.h>
int main(){
for(int i=0;i<20;i++){
char *str=malloc(sizeof(char)*6); //assuming length of each string is 6
scanf("%s",str);
insertinlinkedlist(str);
}
}
whenever i allocate memory here as shown above only the base address of char array will pass to linked list,and that is the memory block allocated for char array is inside main only and i am storing the base address of that array in str which is local to main and is passed to insetinlinkedlist
I want to ask whenever memory is allocated inside loop than why the number of
memory blocks(no of char arrays declared ) are created equal to n (number of time loop runs) since variable name is same we should be directed to same memory location
Note I have checked in compiler by running the loop all the times when loop runs memory the value of str is different
is The above method is correct of allocating memory through loop and through same variable "Is the method ensures that every time we allocate memory in above manner their will be no conflicts while memory allocation and every time we will get the address of unique memory block"
Now above doubt also creates a doubt in my mind
That if we do something like that
int main(){
for(int i=0;i<n;i++){
array[50];
}
}
then it will also create 50 array inside stack frame
malloc returns a pointer to the first allocated byte. Internally it keeps track of how much memory was allocated so it knows how much to free (you do need to insert calls to free() or you'll leak memory, by the way). Usually, it does this by allocating a little bit of memory before the pointer it gives you and storing the length there, however it isn't required to do it that way.
The memory allocated by malloc is not tied to main in any way. Currently main is the only function whose local variables have a pointer to that memory, but you could pass the pointer to another function, and that function would also be able to access the memory. Additionally, when the function that called malloc returns, that memory will remain allocated unless manually freed.
The variable name doesn't matter. A pointer is (to first approximation) just a number. Much like how running int a = 42; a = 20; is permitted and replaces the previous value of a with a new one, int *p = malloc(n); p = malloc(n); will first assign the pointer returned by the first malloc call to p, then will replace it with the return value of the second call. You can also have multiple pointers that point to the same address:
int *a = malloc(42);
int *b = malloc(42);
int *c = a;
a = malloc(42);
At the end of that code, c will be set to the value returned by the first malloc call, and a will have the value returned by the last malloc call. Just like if you'd done:
//assume here that f() returns a different value each time
//it's called, like malloc does
int a = f();
int b = f();
int c = a;
a = f();
As for the second part of your question:
for(int i=0;i<n;i++){
int array[50];
}
The above code will create an array with enough space for 50 ints inside the current stack frame. It will be local to the block within the for loop, and won't persist between iterations, so it won't create n separate copies of the array. Since arrays declared this way are part of the local stack frame, you don't need to manually free them; they will cease to exist when you exit that block. But you could pass a pointer to that array to another function, and it would be valid as long as you haven't exited the block. So the following code...
int sum(int *arr, size_t n) {
int count = 0;
for (size_t i = 0; i < n; i++) {
count += arr[i];
}
return count;
}
for(int i=0;i<n;i++){
int array[50];
printf("%d\n", sum(array, 50));
}
...would be legal (from a memory-management perspective, anyway; you never initialize the array, so the result of the sum call is not defined).
As a minor side note, sizeof(char) is defined to be 1. You can just say malloc(6) in this case. sizeof is necessary when allocating an array of a larger type.

free struct of unions in c

I have a dynamically allocated vector of a special struct, and i trying to free but the software always crashes
the structure is :
typedef struct {
Type_e type;
union {
char m_char;
int m_int;
// more types (non of them is a pointer)
} my_data;
} Data_t;
where Type is an enum that contain all possible data types.
I allocate and initialize the vector as follows
void vector(Data_t **vec, UInt32_t start_element, UInt32_t end_element, Type_e type)
{
UInt32_t i;
Data_t *vec_ptr;
*vec=(Data_t *)malloc((size_t) ((end_element-start_element+1) * sizeof(Data_t)));
vec_ptr = *vec;
if (!vec_ptr)
{
// Write error
}
for (i =start_element; i <= end_element + 1; i++)
{
vec_ptr->type = type;
switch (type)
{
case UINT32: vec_ptr->my_data.m_int = 0; break;
// more possible cases
default:
break;
}
(vec_ptr)++;
}
}
I call this function as follows
Data_t *lVector = NULL;
vector(&lVector,0,10,INT32)
but when I try to free the allocated memory as follows,
free (lVector+start_element-1);
I tried
free (lVector+start_element);
and
free (lVector);
were start_element = 0 (in this case)
But in all cases, it crash. Am I doing anything wrong ?
This is incorrect:
*vec = *vec + sizeof(Data_t);
It advances *vec by sizeof(Data_t)*sizeof(Data_t) bytes, because pointer arithmetics multiplies integral constants by sizeof(*p) automatically.
Replace with (*vec)++, and let the compiler do the math for you. Similarly, remove multiplication in all places where you manipulate pointers. The only place in your code where you need to multiply by sizeof is when you call malloc.
Note: your code is hard to read because you move *vec back and forth as you go through the loop. You would be better off declaring and using a plain temporary pointer for iterating the vector, and keeping *vec fixed to whatever has been allocated by malloc.
You must free exactly the pointer returned by malloc, and do so exactly once. You store the return value of malloc in *vec, so free(*vec) would be correct in the same function or free(lVector) in the calling function. However, you subsequently assign other values to *vec, so to be able to free it correctly you would need to somehow restore the original return value of malloc (a better choice would almost certainly be to use another variable instead).
You also seem to misunderstand pointer arithmetic. p += n already advances the address pointed to by sizeof(*p) * n. So you mustn't multiply the changes to *vec by sizeof(Data_t) (which is sizeof(**vec)).
this parameter says array of pointers to type 'Data_t'
Data_t **vec,
however, this line:
*vec=(Data_t *)malloc((size_t) ((end_element-start_element+1) * sizeof(Data_t)));
allocates memory for an array of 'Data_t' not an array of pointers to 'Data_t'
in C, do not cast the returned value from malloc
the parameter to malloc() is automatically a 'size_t' so casting to 'size_t' just clutters the code
This line:
for (i =start_element; i <= end_element + 1; i++)
iterates over the array from index 0 to index 11 however, the valid index is from 0 to 10 as C array indexs start with 0 and end at sizeof(array) -1
this line:
(*vec)->type = type;
is expecting 'vec' to actually be an array of pointers to struct. But, as mentioned earlier, it is not
this line:
*vec = *vec + sizeof(Data_t);
is properly stepping through the array of struct However, this looses the pointer to the malloc'd memory, resulting in a memory leak because the pointer to malloc'd memory is lost so cannot be passed to free()
This line:
*vec = *vec - ((end_element-start_element+1) * sizeof(Data_t));
doesn't quite work, because the prior 'for' statement iterates one too many times.
Strongly suggest indexing off 'vec' rather than changing vec contents. I.E. vec[i]
Where do you try to call free()?
If inside vector(), you will free '&lVector', which's on the Stack and can't be freed.
You can only free space you allocated with malloc(), so you can free *vec, but not vec.

C Pointer help: Array/pointer equivalence

In this toy code example:
int MAX = 5;
void fillArray(int** someArray, int* blah) {
int i;
for (i=0; i<MAX; i++)
(*someArray)[i] = blah[i]; // segfault happens here
}
int main() {
int someArray[MAX];
int blah[] = {1, 2, 3, 4, 5};
fillArray(&someArray, blah);
return 0;
}
... I want to fill the array someArray, and have the changes persist outside the function.
This is part of a very large homework assignment, and this question addresses the issue without allowing me to copy the solution. I am given a function signature that accepts an int** as a parameter, and I'm supposed to code the logic to fill that array. I was under the impression that dereferencing &someArray within the fillArray() function would give me the required array (a pointer to the first element), and that using bracketed array element access on that array would give me the necessary position that needs to be assigned. However, I cannot figure out why I'm getting a segfault.
Many thanks!
I want to fill the array someArray, and have the changes persist outside the function.
Just pass the array to the function as it decays to a pointer to the first element:
void fillArray(int* someArray, int* blah) {
int i;
for (i=0; i<MAX; i++)
someArray[i] = blah[i];
}
and invoked:
fillArray(someArray, blah);
The changes to the elements will be visible outside of the function.
If the actual code was to allocate an array within fillArray() then an int** would be required:
void fillArray(int** someArray, int* blah) {
int i;
*someArray = malloc(sizeof(int) * MAX);
if (*someArray)
{
for (i=0; i<MAX; i++) /* or memcpy() instead of loop */
(*someArray)[i] = blah[i];
}
}
and invoked:
int* someArray = NULL;
fillArray(&someArray, blah);
free(someArray);
When you create an array, such as int myArray[10][20], a guaranteed contiguous block of memory is allocated from the stack, and normal array arithmetic is used to find any given element in the array.
If you want to allocate that 3D "array" from the heap, you use malloc() and get some memory back. That memory is "dumb". It's just a chunk of memory, which should be thought of as a vector. None of the navigational logic attendant with an array comes with that, which means you must find another way to navigate your desired 3D array.
Since your call to malloc() returns a pointer, the first variable you need is a pointer to hold the vector of int* s you're going to need to hold some actual integer data IE:
int *pArray;
...but this still isn't the storage you want to store integers. What you have is an array of pointers, currently pointing to nothing. To get storage for your data, you need to call malloc() 10 times, with each malloc() allocating space for 20 integers on each call, whose return pointers will be stored in the *pArray vector of pointers. This means that
int *pArray
needs to be changed to
int **pArray
to correctly indicate that it is a pointer to the base of a vector of pointers.
The first dereferencing, *pArray[i], lands you somewhere in an array of int pointers, and the 2nd dereferencing, *p[i][j], lands you somewhere inside an array of ints, pointed to by an int pointer in pArray[i].
IE: you have a cloud of integer vectors scattered all over the heap, pointed to by an array of pointers keeping track of their locations. Not at all similar to Array[10][20] allocated statically from the stack, which is all contiguous storage, and doesn't have a single pointer in it anywhere.
As others have eluded to, the pointer-based heap method doesn't seem to have a lot going for it at first glance, but turns out to be massively superior.
1st, and foremost, you can free() or realloc() to resize heap memory whenever you want, and it doesn't go out of scope when the function returns. More importantly, experienced C coders arrange their functions to operate on vectors where possible, where 1 level of indirection is removed in the function call. Finally, for large arrays, relative to available memory, and especially on large, shared machines, the large chunks of contiguous memory are often not available, and are not friendly to other programs that need memory to operate. Code with large static arrays, allocated on the stack, are maintenance nightmares.
Here you can see that the table is just a shell collecting vector pointers returned from vector operations, where everything interesting happens at the vector level, or element level. In this particular case, the vector code in VecRand() is calloc()ing it's own storage and returning calloc()'s return pointer to TblRand(), but TblRand has the flexibility to allocate VecRand()'s storage as well, just by replacing the NULL argument to VecRand() with a call to calloc()
/*-------------------------------------------------------------------------------------*/
dbl **TblRand(dbl **TblPtr, int rows, int cols)
{
int i=0;
if ( NULL == TblPtr ){
if (NULL == (TblPtr=(dbl **)calloc(rows, sizeof(dbl*))))
printf("\nCalloc for pointer array in TblRand failed");
}
for (; i!=rows; i++){
TblPtr[i] = VecRand(NULL, cols);
}
return TblPtr;
}
/*-------------------------------------------------------------------------------------*/
dbl *VecRand(dbl *VecPtr, int cols)
{
if ( NULL == VecPtr ){
if (NULL == (VecPtr=(dbl *)calloc(cols, sizeof(dbl))))
printf("\nCalloc for random number vector in VecRand failed");
}
Randx = GenRand(VecPtr, cols, Randx);
return VecPtr;
}
/*--------------------------------------------------------------------------------------*/
static long GenRand(dbl *VecPtr, int cols, long RandSeed)
{
dbl r=0, Denom=2147483647.0;
while ( cols-- )
{
RandSeed= (314159269 * RandSeed) & 0x7FFFFFFF;
r = sqrt(-2.0 * log((dbl)(RandSeed/Denom)));
RandSeed= (314159269 * RandSeed) & 0x7FFFFFFF;
*VecPtr = r * sin(TWOPI * (dbl)(RandSeed/Denom));
VecPtr++;
}
return RandSeed;
}
There is no "array/pointer" equivalence, and arrays and pointers are very different. Never confuse them. someArray is an array. &someArray is a pointer to an array, and has type int (*)[MAX]. The function takes a pointer to a pointer, i.e. int **, which needs to point to a pointer variable somewhere in memory. There is no pointer variable anywhere in your code. What could it possibly point to?
An array value can implicitly degrade into a pointer rvalue for its first element in certain expressions. Something that requires an lvalue like taking the address (&) obviously does not work this way. Here are some differences between array types and pointer types:
Array types cannot be assigned or passed. Pointer types can
Pointer to array and pointer to pointer are different types
Array of arrays and array of pointers are different types
The sizeof of an array type is the length times the size of the component type; the sizeof of a pointer is just the size of a
pointer

pointer to array in separate function receiving unwanted garbage values

I have a function that I pass an array into and an int into from my main function. I am doing operations to the array inside this new function, let's call it foo. In foo, I initialize another array with 52 cells all with 0. I do operations on the array that I passed from main, and transfer that data to the newly initialized array. I want to return the new array back to the main function. But of course, I can't return data structures like arrays. So I instead return an int pointer that points to this array. Inside the int main, I pass the pointer to have it point to various cells in the array. When I print the results of what the pointer is pointing to, it should either be pointing to 0 or an integer greater than 0. But instead, I get inconsistent results. For some reason, some of the values that SHOULD be 0, prints out garbage data. I've been trying to spot the bug for some time, but I just wanted a second hand look at it. Here is just the GENERAL idea for the code for this portion anyways...
int main(){
int *retPtr;
char input[] = "abaecedg";
retPtr = foo(input, size);
for(i=0; i<52; i++){
// error displayed here
printf("%d\n", *(retPr + i));
}
}
int foo(char input[], int size)
{
int arr[52] = {0}; // should initialize all 52 cells with 0.
int i=0, value; // looking for non-zero results in the end.
int *ptr = &arr[0];
for(i=0; i<size; i++){
if(arr[i] > 64 && arr[i] < 91){
value = input[i] - 65;
arr[value]++;
}
}
return ptr;
}
Hopefully this makes sense of what I'm trying to do. In the foo function, I am trying to find the frequency of certain alphabets. I know this might be a bit cryptic, but the code is quite long with comments and everything so I wanted to make it as succinct as possible. Is there any possible reason why I'm getting correct values for some (numbers > 0, 0) and garbage values in the other?
The reason you get garbage back is that the array created in foo is allocated in foos stack frame, and you then return a pointer into that frame. That frame is discarded when foo returns.
You should allocate the array on the heap (using malloc and friends) if you want it to remain after foo returns. Don't forget to free() it when you're done with the array.
int main(){
char input[] = "abaecedg";
int retPtr[] = foo(input, size); //An array and a pointer is the same thing
...
free(retPtr);
}
int *foo(char input[], int size)
{
int arr[] = calloc(52*sizeof(int); // should initialize all 52 cells with 0.
...
arr[value]++;
...
return arr;
}
Another way is to let foo take an array as a parameter and work with that, in this way:
int main(){
int ret[52] = {0};
...
foo(input, size, ret);
...
}
void foo(char input[], int size, int *arr)
{
...
arr[value]++;
...
return; //Don't return anything, you have changed the array in-place
}
The reason this works is because an array is the exact same thing as a pointer, so you are really passing the array by reference into foo. arr will be pointing to the same place as ret, into the stack frame of main.
In function foo the array arr is a local array, that is, allocated on the stack. You must not return any pointer of data allocated on the stack, since the stack is rewinded after you return from the function, and its content is no more guaratneed.
If you want to return an array you should allocate it on the heap using malloc, for example, and return the pointer malloc returned. But you will then have to free that memory somewhere in your program. If you fail to free it you will have what's called a "memory leak", which may or may not crash/disturb this program from running again, depending on your environment. A not clean situation, that's for sure.
That's why I consider C not so good for functional programing idioms, such as returning things from function (unless they are primitive types). I would achieve what you tried to do by passing another array to foo - an output array, companioned by a size variable, and fill that array.
Alternately, you could wrap the array within a struct and return that struct. Structs can be returned by value, in which case they are copied via the stack to the caller function's returned value.

Double pointer memory allocation to a struct in C

Can't find what is wrong with this code, it works as expected when inputting exactly 4 values, but on the fifth call (before it even asks for scanf) it always gives me this error:
* glibc detected ./a2: double free or corruption (fasttop): 0x0916e018 **
Here's some code of my program:
typedef struct {
int i;
char str[25];
} typeX;
int main(){
int dSize = 0;
int *dSizePtr = &dSize;
dPointer = (typeX **)malloc(sizeof(typeX *)); // makes an array of pointers
int i;
for (i = 0; i < 100; i++)
makeElement(dPointer, dSizePtr); // Puts values into those pointers
free(dPointer);
return 0;
}
void makeElement(dPointer **, int *dSizePtr){
dPointer = (typeX **)realloc(dPointer, sizeof(typeX *)*(*dSizePtr+1)); // grow the array by one
if (typeX == NULL)
return; // some kind of quit statement, just return for now
dPointer[*dSizePtr] = (typeX *)malloc(sizeof(typeX)); // make a new pointer in the array
scanf("%s", dPointer[*dSizePtr]->str); // input the values of the struct (have to use scanf)
char input[20];
scanf("%s", input);
dPointer[*dSizePtr]->int = atoi(input);
++(*dSizePtr);
}
I know I don't have to make a dSizePtr and I can just pass in &dSize, but the way my program is currently set up (this isn't exactly the same, just compressed for readability), that's the way I have to pass it.
I honestly have no idea why this error is coming up. Been looking at my code for hours and reading online and haven't found a solution. Any help will be greatly appreciated!
The problem is that your function makeElement get the value of dPointer, not its reference. When you realloc the data, the originally allocated chunk is freed. But the dPointer outside of the makeElement scope is not changed;
The runtime error is delayed as the actual memory allocation is performed in quantities bigger than sizeof(typeX*)
This line is causing the double free.
dPointer = (typeX **)realloc(dPointer, sizeof(typeX *)*(*dSizePtr+1)); // grow the array by one
For the first few iterations of the loop in the caller the block of memory is large enough that realloc() doesn't have to do anything, and thus it returns the same pointer passed to it. But at some point the block of memory is too small and realloc() has to allocate a new block of memory and returns a pointer to it. That returned pointer is assigned to dPointer in makeElement() but it does not change the value of dPointer in the caller. So the caller continues to pass the old dPointer value into makeElement(), which passes it to realloc(), which notices that this pointer has been freed (by the call to realloc() that expanded the size of the array).

Resources