char** removeDuplicateChromosomes(char* input[], int no_of_chromosomes)
{
char** result = (char**) malloc(sizeof(char* )*(no_of_chromosomes));
//some piece of code
result[count] = input[itr];
//some piece of code . I didn't free any pointers here in this function
return result;
}
Can someone help me to identify any dangling pointers (if present) and explain the same pls?
Memory leak - if no pointer points to unfreed memory.
Dangling pointer - a pointer that points to freed memory.
Your code has a significant risk of either / both, though without a complete code sample, it's impossible to tell whether either would occur. I'll just give some possible scenario's of when it could happen.
As an initial note, If you don't free result's memory in the calling function, you'd have a memory leak. Any malloc must have a corresponding free.
If you free input like this:
free(input);
There would not be a dangling pointer.
But then there may be a memory leak if each element of input doesn't have an element of result pointing to the same memory. And if multiple elements of result point to this memory, you'll probably end up with a dangling pointer when you try to free it, along with some undefined behaviour.
If you free input like this:
int i;
for (i = 0; i < inputSize; i++)
free(input[i]);
free(input);
There would be a dangling pointer.
Why?
input[itr]; is a pointer.
result[count] = input[itr]; just makes result[count] point to the same memory as what input[itr] points to.
So if we free input[itr], result[count] would point to freed memory, and thus be dangling.
If we don't free input[itr], result[count] will still point to valid memory.
If you want result[count] to point to its own memory, you'll have to use:
result[count] = malloc(inputItrSize);
memcpy(result[count], input[itr], inputItrSize);
Note - there's no way to tell how much memory input[itr] is pointing to, so you'll have to declare inputItrSize with the appropriate size yourself.
A dangling pointer is a pointer to a memory area that is no-longer allocated.
char* dangleMeBaby(char* obj) {
free(obj);
return obj;
}
int* localDangle() {
int i = 10;
return &i;
}
#define NUM_POINTERS 8
char** wholeLottaDangle() {
char* ptr = malloc(sizeof(char*) * NUM_POINTERS);
size_t i;
void* data = malloc(NUM_POINTERS);
for (i = 0; i < NUM_POINTERS; ++i) {
ptr[i] = data + i;
}
free(data); // all the pointers in ptr now dangle.
free(ptr); // and ptr itself is now a dangle
return ptr;
}
If you have allocated input as one big block of pointers + data, then freeing input before result will turn result into an array of dangling pointers.
size_t indexSize = sizeof(char*) * numChromosomes;
size_t chromosomeSize = (MAX_CHROMOSOME_LEN) * numChromosomes;
char* data = malloc(indexSize + chromosomeSize);
char** input = (char**)data;
char* chromosome = data + indexSize;
for (size_t i = 0; i < numChromosomes; ++i, chromosome += MAX_CHROMOSOME_LEN) {
input[i] = chromosome;
}
// no dangling pointers in result until you free input.
If you have allocated chromosomes individually and then allocated "input" to house all the pointers, then freeing a chromosome without removing it from "result" will cause a dangling pointer
result = removeDuplicateChromosomes(input, 64);
free(input[0]); // result still points to it, result is dangling.
But if input and the list of chromoes remain intact until you free input() and/or any chromosomes, you have no dangling pointers.
Related
I am getting the memory leak due to first malloc call. I tried to comment out and free but there is no way that I can fix it.
The code wants to parse the query than put the information inside the map. At the same time it is going to update struct too
row_ = atoi(strtok(NULL,",:"));
col_ = atoi(strtok(NULL,",:"));
}
}
For starters this for loop
for(int j = 0; j < strlen(query); j++){
if(!strcmp(&query[j], ",")){
count++;
}
}
does not make a sense. It seems you mean instead
for(int j = 0; j < strlen(query); j++){
if( query[j] == ',')){
count++;
}
}
You allocated memory and its address is assigned to the pointer type.
char* type = malloc(sizeof(char *));
// char* char_name= (char *)malloc(1);
then the pointer was reassigned
type = strtok(query, ",:");
So the address of the allocated memory is lost and you have a memory leak.
This commented declaration
char* char_name= (char *)malloc(1);
also invokes a memory leak due to the statement
char_name = strtok(NULL,",:");
This statement
char_name = realloc(char_name, sizeof(char_name)+1);
does not make a sense at least because sizeof( char_name ) is equivalent to sizeof( char * ). It seems you mean at least
char_name = realloc(char_name, strlen(char_name) + 2 );
But in any case you may not reallocate the memory using the pointer because it does not point to a dynamically allocated memory after this statement
char_name = strtok(NULL,",:");
examine these 2 lines of code
char* type=malloc(sizeof(char *)); <<<<<<=======
// char* char_name= (char *)malloc(1);
int row_,col_;
int count =0;
for(int j=0;j<strlen(query);j++){
if(!strcmp(&query[j],",")){
count++;
}
}
count=(count+1)/3;
type = strtok(query, ",:"); <<<<<<=======
You malloc some memory, do nothing with it and then overwrite the pointer. So now there is no way to free it or use it.
As far as I can see you just need
char*type = NULL;
and take out the frees of type too.
Note - I have not verified the rest of the code. Just answered your leak question. The way you are using strtok is certainly not idiomatic. And I suspect that you think
type = strtok(query, ",:");
copies the first token into the buffer pointed at by type. It does not, what you need is this
type = strdup(strtok(query, ",:"));
Likewise the assignments in the loop
char_name = strtok(NULL,",:");
char_name = realloc(char_name, sizeof(char_name)+1);
are very wrong. You cannot realloc the return of strtok. Again you need
char_name = strdup(strtok(NULL,",:"));
I have an array that I want to increase the size of during runtime. I assign values to the elements of the array by using a loop, and when the index of the loop hits the number of elements of the array, I want to increase the size of the array.
What I did, actually works; I can assign values to elements of the array that I would normally not be able to assign any values to without increasing the array's size. The bad side is, it gives me a crash after the program runs and finishes smoothly. What is wrong here? Is it that maybe the memory that I try to allocate for the array is already filled?
int main()
{
int arr[3];
int num_of_elements = sizeof(arr)/sizeof(arr[0]); // This gives '3', I checked
for(i = 0; i < 10; i++)
{
if(i == num_of_elements)
{
num_of_elements = num_of_elements + 10;
realloc(arr, num_of_elements);
}
arr[i] = i+10;
printf("%d\n", arr[i]);
}
return 0;
}
Well you are invoking undefined behavior. From standard ยง7.22.3.5
void *realloc(void *ptr, size_t size);
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.
By memory management function - it means malloc etc. arr is not dynamically allocated memory. So passing this to realloc is undefined behavior - in your case that behavior leads you to crash in program.
It would work if you do this
int *arr = malloc(sizeof(int)*3);
if( arr == NULL){
perror("Malloc failed");
exit(EXIT_FAILURE);
}
...
int *p = realloc(arr,num_of_elements*sizeof(int));
^^^^^
if(p == NULL ){
perror("realloc failed");
exit(EXIT_FAILURE);
}
arr = p;
Check how realloc is used.
The takeaways will be:-
Check the return value of realloc, malloc.
You were trying to reallocate extra 10 elements for which you need 10*sizeof(int) amount of memory.
Don't do arr = realloc(arr,SIZE) in case realloc fails you will have memory leak.
Why realloc to p after all you do arr=p annyway?
Two reasons so far
The answer to this is when realloc fails then it returns NULL now if you assign arr to NULL then you may have a situation where you lose the only reference to the previously allocated memory - leading to a memory leak. That's why we do it like this.
Note this from standard
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.
Notice that may part - it might be the same address as before as pointed by arr or it might be different one. That explains why we should store it in some temporary pointer and then we assign it later.
You should have done this:
arr = realloc(arr, num_of_elements);
^^^^^
realloc() does not necessarily extend or shrink the allocated memory in-place, it invalidates the dynamic memory that its first argument points to and allocates new memory, while preserving the content of the previous memory.
One possible implementation is :
void* realloc(void* ptr, size_t size) {
void* ret = malloc(size);
if (ret == NULL) return ret;
if (ptr != NULL) {
memcpy(ret, ptr, /* previous size from system */);
free(ptr);
}
return ret;
}
I am debugging some code written by someone else which has several memory leaks detected by Valgrind. Part of the code which I believe is causing the problems involves void pointers:
int noElements = 100;
void** ptr = malloc( noElements * sizeof(void*));
for(int i = 0; i < noElements; i++)
{
ptr[i] = malloc(sizeof(void*));
}
//Operation filling the array and doing calculation
free(ptr); //This will not clear the underlying array causing the memory leak?
I created a small test program to check the error is where I thought it was (not freeing each ptr[i] before calling free(ptr);), but I am getting errors when trying to free elements. My test program looks like this:
int main()
{
int num = 10000000; //Large array so I can clearly see memory usage
void** ptr = (void**) malloc(sizeof(void*) * num);
for (int i = 0; i < num; i++)
{
ptr[i] = malloc(sizeof(void*));
ptr[i] = &i; //If I never point elements at anything, this code works
}
for (int i = 0; i < num; i++)
{
free(ptr[i]); //Crashes here if the elements have been pointed at a variable
}
free(ptr);
return 0;
}
Why would calling free on each array element cause the program to crash if the pointers have actually been assigned?
In your code
ptr[i] = &i;
creates three issues.
It makes the actual returned pointer by malloc() to be lost (you're overwriting it), so you have no shot at free()-ing it later, leading to memory leak.
i is a local scoped variable (the scope of for loop body), and you're storing the address of the variable to be used outside the scope (i.e., after the lifetime is over). Outside the scope attempt to access the address of it will invoke undefined behavior.
(Ignoring point 2) Attempt to free() the ptr[i] will cause undefined behavior again, as the pointer is not returned by memory allocator function.
Your pointers have been assigned a value which is not what you want.
for (int i = 0; i < num; i++)
{
ptr[i] = malloc(sizeof(void*));
ptr[i] = &i; //If I never point elements at anything, this code works
}
First you assign a valid memory address that is returned by malloc().
This address could be free'd using free().
But then you assign another address. The address of your local variable i. This memory location was not allocated using malloc() and hence cannot be free'd. By assigning this address you've lost the dynamically allocated address causing a memory leak.
Your comment is wrong. You already assigned a value that ptr[i] points to some valid address. You don't need to assign again. And you should not.
This question already has answers here:
Using realloc to shrink the allocated memory
(5 answers)
Closed 2 years ago.
I have a question about the realloc function. Will the content of old pointer be changed after apply realloc function?
The code is
main () {
int *a, *b, i;
a = calloc(5, sizeof(int));
for (i = 0; i < 5; i++)
a[i] = 1;
for (i = 0; i < 5; i++)
printf("%d", a[i]);
printf("\n%p\n", a);
b = realloc(a, 200000 * sizeof(int));
if(b == NULL)
printf("error\n");
for (i = 0; i < 5; i++)
printf("%d", a[i]);
printf("\n");
for (i = 0; i < 10; i++)
printf("%d", b[i]);
printf("\n%p %p\n", a, b);
}
The output is
11111
0x2558010
00111
1111100000
0x2558010 0x7f29627e6010
Pointer a still point to the same address, but the content is changed.
Pointer a still point to the same address, but the content is changed.
That's because realloc() may first try to increase the size of the block that a points to. However, it can instead allocate a new block, copy the data (or as much of the data as will fit) to the new block, and free the old block. You really shouldn't use a after calling b = realloc(a, 200000 * sizeof(int)) since the realloc call may move the block to a new location, leaving a pointing to memory that is no longer allocated. Use b instead.
The value returned by realloc tells you whether it succeeded or failed.
b = realloc(a, 200000 * sizeof(int));
If it fails, it returns a null pointer, and a still points to the original unmodified chunk of memory (and of course b is a null pointer).
If it succeeds, then b points to a (possibly newly allocated) chunk of memory, and the value of a is indeterminate. If it was able to allocate the new chunk in the same place as the old one (by growing or shrinking the chunk in place), then b will be equal to a -- but testing that, or even referring to the value of a, has undefined behavior. If it has to relocate the chunk, then realloc will have done the equivalent of free(a) after copying the data. In either case, it's probably best to set a to NULL to avoid accidentally referring to its (now indeterminate) value.
Note that realloc can relocate chunk even if the new size is smaller.
A simple realloc implementation should answer your questions:
void * realloc(void * ptr, size_t desired_size) {
size_t allocated_size = _allocated_size_of(ptr);
if (allocated_size < desired_size) {
void * new_ptr = malloc(desired_size);
memcpy(new_ptr, ptr, allocated_size);
free(ptr);
ptr = new_ptr;
}
return ptr;
}
malloc and related functions don't always allocate exactly the desired size. Very often they allocate more than the desired size. There is some hidden data kept up with by the memory allocation functions which allows for a pointer that was allocated by malloc or related functions to be used to look up the memory block size that was allocated. How this is kept up with isn't necessary to understand, but some very simple implementations simply store the size in the space just before the pointer returned *(((size_t)ptr)-1).
If realloc() returns a pointer different from the one you passed in (as it will most of the time), then the pointer you passed in no longer belongs to you, and you have no business knowing or caring what becomes of it. It might change its contents, it might not. But you are no longer allowed to access it, so it can be no concern of yours.
If 'a' points a valid block of memory (from a previous malloc/realloc/calloc), then a realloc call will attempt to provide a block of memory with the new size you requested
The realloc call should be of the form *tmp = realloc (a ...
The return value from realloc must be tested
If it is NULL, realloc was unable to allocate the requested memory, and this leaves 'a' as a valid pointer
You are then responsible for handling any data pointed to by 'a' (save it / discard it) and you are responsible for free ing the memory pointed to by 'a'
If the realloc call was successful make b = tmp and now 'b' is the new pointer to the block of memory - it does not matter whether the start location is the same as 'a' or different. 'a' is no longer a valid memory allocation pointer, although further errors will depend on whether 'a' points to memory owned by your program or not - basically if a == b, 'a' can be accessed without obvious errors.
After a valid *tmp = realloc(a ... & b = tmp;:
1) If the start location of the reallocated memory was unchanged: (a == b)
it will allocate the requested memory
but run it under valgrind and you will see error messages:
Invalid free() / delete / delete[] / realloc()
Address 0x51fc040 is 0 bytes inside a block of size 256 free'd
In this case realloc could not free the memory pointed to by 'a'
and again in this case 'a' can still be accessed as it is a pointer to memory that is allocated to your progam
2) If the start location of the reallocated memory was changed: (a != b)
it will fail and Valgrind shows output like this:
address of a: 0x1e89010
address of b: 0x7f2c5893c010
a after realloc: 0x1e89010
Error in `./test15': realloc(): invalid old size: 0x0000000001e89010
and trying to access 'a' will fail - even trying to print it's value as a pointer fails, presumably because it no longer points to memory owned by the program
In other words, using 'a' after b = realloc(a ... is undefined behaviour.
The above commentary was based on using the following code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *a = NULL, *b = NULL, *c = NULL;
/* initial allocation */
a = malloc(256);
if( a == NULL) return (1);
printf("address of a: %p\n", a);
/* reallocation 'b' MAY be same as 'a' - try much larger allocations */
void *tmp = realloc(a, 512);
if ( !tmp ) {
free(a);
return (1);
} else {
b = tmp;
}
printf("address of b: %p\n", b);
/* see what 'a' is now - this MAY crash the program*/
printf("a after realloc: %p\n", a);
/* 'a' may not be a valid pointer - try using it for another realloc */
c = realloc(a, 256);
/* Valgrind shows that memory could not be free'd or 'a' was not valid allocated memory */
printf("return value of c: %p\n", c);
if (c != NULL) {
free(c);
printf("'c' allocated\n");
} else {
free(b);
printf("'c' not allocated\n");
}
return 0;
}
Reading the man page is key here, but the TLDR is if there isn't enough memory to enlarge at the back end of the previous block, it will get a new block of memory, copy the old data into it, and return the address of the new block. The old address should not be used, and most typical realloc statement looks like this
a = realloc(a, 200000 * sizeof(int));
That way you won't accidentally use the possibly wrong old value.
It can't change the address in the pointer, since it is passed by value, so changing it in the function is only changing the local copy.
EDIT : Per Weather Vane's absolutely correct comment, the safer route would be
void * b = realloc(a, 200000 * sizeof(int));
if ( b ) {
a = b;
} else {
;;; /* error handler here */
}
What is the right way to malloc memory ? And what is the difference between them ?
void parse_cookies(const char *cookie, cookie_bank **my_cookie, int *cookies_num)
{
*my_cookie = malloc(sizeof(cookie_bank) * 1);
*my_cookie = (cookie_bank *)malloc(sizeof(cookie_bank) * 1);
my_cookie = (cookie_bank **)malloc(sizeof(cookie_bank) * 1);
///
}
I'm trying to malloc array of cookie_bank structs function.
I'm assuming that you want the function to allocate memory for an array and passing the result via a pointer parameter. So, you want to write T * x = malloc(...), and assign the result to a pointer argument, *y = x:
cookie_bank * myarray;
parse_cookies(..., &myarray, ...);
/* now have myarray[0], myarray[1], ... */
So the correct invocation should be, all rolled into one line,
parse_cookies(..., cookie_bank ** y, ...)
{
*y = malloc(sizeof(cookie_bank) * NUMBER_OF_ELEMENTS);
}
Your second example is the most correct. You don't need the *1 obviously.
*my_cookie = (cookie_bank *)malloc(sizeof(cookie_bank) * 1);
Your first example is also correct, although some compilers/flags will cause a complaint about the implicit cast from void*:
*my_cookie = malloc(sizeof(cookie_bank) * 1);
It you want to allocate more than one entry you'd generally use calloc() because it zeros the memory too:
*my_cookie = (cookie_bank*)calloc(sizeof(cookie_bank), 1);
your third example is just wrong:
my_cookie = (cookie_bank **)malloc(sizeof(cookie_bank) * 1);
This will overwrite the local my_cookie pointer, and the memory will be lost on function return.
I just would like to recommend you to read some C textbook. It seems to me that you do not have clear understanding on how pointers work in C language.
Anyway, here is some example to allocate memory with malloc.
#include <stdlib.h>
void parse_cookies(const char *cookie, cookie_bank **my_cookie, int *cookies_num)
{
if (cookies_num == NULL || *cookies_num == 0) {
return;
}
if (my_cookie == NULL) {
my_cookie = (cookie_bank**)malloc(sizeof(cookie_bank*) * *cookies_num);
}
for (int i = 0; i < *cookies_num; i++) {
*my_cookie = (cookie_bank*)malloc(sizeof(cookie_bank));
my_cookie++;
}
}
Of course, this example does not cover any error handling. Basically, my_cookie is pointer to pointer which means my_cookie is just pointer to point memory location where it holds array of pointers. The first malloc allocate the memory using size of pointer and requested number of cookie structure. Then second malloc actually allocate memory for each structure.
The problem of this function is that it can easily cause memory leak unless using this very carefully.
Anyway, it is important to understand how C pointer works.