Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
How to deallocate memory for the following code: I want to store names in name field of the given below structure struct tag and then deallocate the memory
SINT32 TestExample(void)
{
typedef struct tag
{
char *name;
} ST;
int i;
ST **p, **p1;
p = p1 = (ST **)calloc(1, 10 * sizeof(ST *));
for(i=0; i<10; i++)
{
p[0] = (ST *)calloc(1, 10 * sizeof(ST));
p[0]->name = (char *)malloc(20 * sizeof(char));
sprintf(p[0]->name, "Name_%d", i);
++p;
}
/* TO DO: free the memory allocated in previous block */
{
------------------------
}
p = NULL:
return 0;
}
Call free(object) on the same objects you called malloc on in a for loop
You should free name before freeing the struct.
p = p1;
for(i=0; i<10; i++)
{
free(p[i]->name);
free(p[i]);
}
free(p1);
The basic idea is that you should free the things you allocate memory to, in an order that allows you to free the other things.
You also need to "reset" the pointer p to the original address by doing p = p1;
as you can see here by doing
free(p);
be careful not to free memory that wasn't allocated, so you won't get debug assertion failed.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I want to define a 2D array with size 20*100000 in C. I do not want to keep the size fixed.
double **twod = malloc(20 * sizeof(double *));
int i;
if (twod == NULL)
abort();
for (i = 0; i < 20; ++i)
if ((twod[i] = malloc(100000 * sizeof(double))) == NULL)
abort();
// clean up
for (i = 0; i < 20; ++i)
free(twod[i]);
free(twod);
The first malloc call allocates space for 20 double pointers. Each double pointer will point to a subarray.
The second malloc call in the loop allocates 100000 doubles in each subarray.
The free calls do the inverse of malloc--they return memory to free store. First, each subarray must be freed, in a loop. Then the entire array itself must be freed too.
The return value of malloc is examined against NULL. If malloc returns NULL, then the system is out of memory. This is important since you are allocating HUGE amounts of memory. If malloc returns NULL, the application is aborted.
You'll need to define a pointer to pointer and initialize it like this:
int i;
double **array;
array = malloc(sizeof(double *)) * 20);
for (i=0; i<20; i++) {
array[i] = malloc(sizeof(double) * 100000);
}
Don't forget to free the memory when you're done with it.
You can use a Variable-length array (since C99) in order to avoid fragmentation:
double (*array)[cols];
array = malloc(sizeof(*array) * rows);
In this way calling free(array); is enough.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
So, this is working fine... that means, no compiler errors, it seems that there is no memory leak and it is doing what I wanted it to do. That said should it be working? When I go to books_init I send a local variable to collection, doesn't it mean that when I go back to main it shouldn't be working? (or undefined behavior?). Also, in case you say that I have to malloc it, do I have to free it after? (commented on cleanup)
/* pseudo struct Collection{
size_t size, capacity;
Volume *volumes;
} */
void collection_init(Collection *col, size_t capacity){
col->size = 0;
col->capacity = capacity;
col->volumes = malloc(sizeof(Volume) * capacity);
}
void collection_resize(Collection *col, size_t capacity){
Volume *v = realloc(col->volumes, capacity * sizeof(Volume));
if(!v) return;
col->capacity = capacity;
col->volumes = v;
}
void collection_add(Collection *col, Volume *volume){
if(col->size >= col->capacity)
collection_resize(col, col->capacity * 2);
col->volumes[col->size++] = *volume;
}
void collection_clean(Collection *col){
//for(vol : col->vol) free(vol);
//should I free every element or just volumes?
free(col->volumes);
}
void books_init(Collection *col){
for(int i = 0; i < 25; ++i){
Volume v = {.swag = i};
collection_add(col, &v);
}
}
int main(){
Collection col;
collection_init(&col, 10);
books_init(&col);
for(int i = 0; i < col.size; ++i){
printf("\tVol[%d].id = %d\n", i, col.volumes[i].swag);
}
collection_clean(&col);
return 0;
}
Thanks for your time
This line in books_init
Volume v = {.swag = i};
creates a local variable called v with member swag initialized to i. The address of that variable is then passed to collection_add. That is allowed because v is still in scope.
This line in collection_add
col->volumes[col->size++] = *volume;
makes a copy of the contents of the Volume structure, and stores that copy in the memory that was allocated in collection_init.
After collection_add returns, the variable v in books_init goes out of scope, but that's OK because the contents of v were copied and saved in the memory that col->volumes points to.
When the program ends, collection_clean only needs
free(col->volumes);
to remove all of the Volume copies from memory.
The only flaw I see in your program occurs if realloc fails. In that case, you still write to the Volume array. This will cause a buffer overrun and memory corruption. To avoid this, the collection_add function should verify that the collection_resize function succeeded before performing the copy. For example, you could check again that col->capacity > col->size before doing the copy.
TL;DR your code is fine as long as the realloc always succeeds.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I have the following data structure:
struct Stack {
Vector* m_intArray; /*vector is stored here*/
int m_numOfElements;
};
struct Vector {
int* m_intArray; /*pointer to array of ints, data stored here*/
int m_intArrayCurrentSize;
int m_intArrayCapacity;
int m_blockSize;
int m_initialSize;
};
The vector structure is written in a different file (vector.c) with function
Vector* VectorCreate(size_t _initialSize, size_t _blockSize)
which creates the vector structure and allocates memory for the array of ints in it. In the file stack.c I've written the function
Stack* StackCreate(size_t _initialSize, size_t _blockSize)
which creates the stack structure and calls VectorCreate in the "m_intArray" field of stack. When I call StackCreate from main, I see uding the debugger that inside the function, everything is OK and there is memory allocated for all three pointers (pointer to stack, pointer to vector and pointer to int)
(gdb) p stackPtr
$11 = (Stack *) 0x603010
(gdb) p stackPtr->m_intArray
$12 = (Vector *) 0x603030
(gdb) p stackPtr->m_intArray->m_intArray
$13 = (int *) 0x603050
When the function ends and returns the Stack pointer back to main, the int* pointer is nulled.
(gdb) p testStack
$14 = (Stack *) 0x603030
(gdb) p testStack->m_intArray
$15 = (Vector *) 0x603050
(gdb) p testStack->m_intArray->m_intArray
$16 = (int *) 0x0
I can't seem to find the reason it happens, pretty much clueless in this case. Never ran into it before, will appreciate your help.
Heres the Stack Create
Stack* StackCreate(size_t _initialSize, size_t _blockSize)
{
if (_initialSize == 0 && _blockSize == 0)
{
return NULL;
}
Stack* stackPtr = ((Stack*)malloc(sizeof(Stack)));
if (stackPtr == NULL)
{
return NULL;
}
stackPtr->m_intArray = VectorCreate(_initialSize, _blockSize);
if (stackPtr->m_intArray == NULL)
{
free(stackPtr);
return NULL;
}
}
Looks like you're returning the wrong pointer. Notice how in the first GDB segment, the stack pointer is 0x603010, but in the second segment, it's 0x603030, which is the vector pointer in the first chunk.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
well, i'm working in C. I want to make a function that return a matrix[][].
This is my function:
char **mapa(int largo,int ancho)
{
char **matriz;
int i,j;
matriz = (char **)malloc(sizeof(char)*largo);
for(i = 0; i < largo; ++i)
{
matriz[i]= (char *)malloc(sizeof(char)*ancho);
}
for(i = 0; i < largo; i++)
{
for(j = 0; j < ancho; j++)
{
matriz[i][j] = 'k';
}
}
for(i = 0; i < largo; i++)
{
for (j = 0; j < ancho; j++)
{
printf("%c",matriz[i][j]);
}
}
return matriz;
}
Using gdb it give me this:
Program received signal SIGSEGV, Segmentation fault.
0x00000000004008b8 in mapa (largo=10, ancho=10) at main.c:18
18 matriz[i][j] = 'k';
I don't know where the error is, if someone can give me a hand i'll be very gratefull.
Many thanks.
char **matriz;
int i,j;
matriz = (char **)malloc(sizeof(char)*largo);
Your matriz variable is a pointer to an array of pointers, each of which points to an array of char. You first need to allocate memory for the array of pointers, which requires largo times the size of the pointers, which is sizeof (char *). You only allocate space for largo times the size of a single char.
The easiest way to get the allocation right is to use the following pattern:
p = malloc (n * sizeof *p);
In other words, allocate n times the size of whatever p points to. This will automatically allocate the right amount regardless of the type of p, assuming you get the n right. If you're declaring the pointer in the same line, it looks a little different:
T *p = malloc (n * sizeof *p); /* For some type T */
In this case there is an asterisk before p on both sides. This difference is something you will have to be aware of, especially when you have more than one level of indirection.
Your first allocation, using this pattern, would look like this:
matriz = malloc (largo * sizeof *matriz);
and the second:
matriz[i] = malloc (ancho * sizeof *matriz[i]);
Note, that you never have to cast a void pointer (the return value of malloc()), and that the argument to the sizeof operator only needs parenthesis when it's a type name. When you get rid of the parenthesis, and place the quantity (ancho) before the sizeof operator, the result is an expression that is very clean and easy to understand. That is, of course, my personal opinion.
Your first malloc casts to a pointer of pointer's but that doesn't mean it is. If you look at your 2nd malloc you're allocating the same thing. So when you dereference matriz[i][z] you're dereferencing a charater, not a pointer. So I believe, it's been a while since I've done C, your first malloc needs to be (char**)malloc(sizeof(char*)*largo).
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
We assume that there are 200 bytes of memory in our processor.
Here's the code:
#include <stdlib.h>
char * p;
char data;
void test1()
{
p = (char *)malloc(sizeof(char) * 300);
p[0] = 1;
}
void test2()
{
p = (char *)malloc(sizeof(char) * 300);
data = p[5];
}
When I run the "test1()", obviously there will be a memory overflow. However "test2()" will not. Does the compiler optimized the memory in "test2()" ? How?
And there's another strange problem:
void test3()
{
char ele[1000]={0};
}
void test4()
{
char ele[1000];
ele[999] = 10;
}
The "test3()" will cause memory overflow, and "test4()" will not.
Sorry for my bad English,and thank you for your answer.
======================================================
Finally,I figure that out. I checked the assembly code, in “test3” it allocated memory indeed.But in "test4" ,the compiler optimized the array, does not allocated memory for it.
Thanks #Philipp,Thanks all.
When malloc fails because it can't allocate enough memory, it won't crash. It will return the memory address 0 instead.
When you neglect checking the return-value and treat that value as an array, you can still read from it. The reason is that the operator [5] means basically as much as "start from that address, move 5 steps ahead in memory, and read from there". So when p is 0, and you do data = p[5];, you read whatever is at memory address 5. This isn't the memory you allocated - it's whatever is in memory at that location.
But when you try to write something to p[0], you are trying to write to memory address 0 which is not allowed and will lead to a runtime error.
Bottom-line: Whenever you do malloc, check the return value. When it's 0, the memory allocation has failed and you have to deal with that.
When you request a memory allocation which is greater than available memory, malloc() simply returns NULL. For checking this just add error checking to your code like,
#include <stdlib.h>
char * p;
char data;
void test1()
{
p = (char *)malloc(sizeof(char) * 300);
if(p == NULL)
{
printf("Failed to allocate memory\n");
return -1;
}
p[0] = 1;
}
void test2()
{
p = (char *)malloc(sizeof(char) * 300);
if(p == NULL)
{
printf("Failed to allocate memory\n");
return -1;
}
p[0] = 1;
data = p[5];
}
The above calls simply returns error in your case.