I got and error which says
Debug assertation failed and heat corruption detected
like everything is working good in my program but I get that error. Where is the memory leak here? I have to free that memory in the main because my functions need to return pointers.
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *dynamic_reader(unsigned int n) {
/*making new array and checking if allocation succeeded*/
int *mem;
mem = malloc(n * sizeof(int));
if (!mem) {
printf("Memory allocation failed\n");
exit(-1);
}
/*letting the user to input the values for the array*/
int i = 0;
while (i < n) {
scanf("\n%d", &mem[i]);
i++;
}
/*printing the array just to make sure everything is good*/
for (int j = 0; j < n; j++) {
printf("%d ", mem[j]);
}
return mem;
}
int *insert_into_array(int *arr, unsigned int num, int newval) {
/*making new bigger array*/
int *newarr = realloc(arr, (num + 1) * sizeof(int));
/*adding the integer to this new array */
newarr[num] = newval;
printf("\n");
/*printing to make sure everything is correct*/
for (int j = 0; j < num + 1; j++) {
printf("%d ", newarr[j]);
}
return newarr;
}
int main(void) {
/*In dynamic_reader function I need to make an array which size is given as a parameter*/
/*In this case I choosed 3*/
int *arr = dynamic_reader(3);
int num = 3;
/*In insert_into_array function I need to add one integer to this array I made in dynamic_reader*/
/*The parameters are the array, the number of elements in the array already done and the integer I want to add*/
int *c = insert_into_array(arr, num, 9);
/*I free the memory here because I need to return the pointers of these arrays in the function so it cant be done there*/
free(arr);
free(c);
}
You are double freeing your memory. Check the documentation for realloc. Realloc will either 1) expand the passed buffer or 2) will allocate a new buffer, copy the data, and free the original buffer. When you do:
free(arr);
free(c);
You are double freeing a value that was either once already freed by realloc or already freed by the first free(arr)
Additionally, you should check if realloc fails (returns NULL) and if so, handle the case appropriately.
First you malloc an array, which you return to your main function as arr. Then in another function, you realloc where arr is an argument to the realloc, but some other pointer stores the results. Depending on what happened in realloc, you've either got arr and newarr pointing to the same location, or newarr pointing to a valid location and arr pointing to an invalid location that has been freed. Either way, freeing both of them at the end is a problem.
No need to free(arr), that is taken care of when you realloc() it. The pointer returned by realloc() will either point to memory which includes the original memory, or free the old memory after copying its content to a new, larger chunk of memory.
Related
This code is meant to copy an int array with count elements to a newly applied memory area in the heap.
int copy(int *array ,int count){
int i;
int *myarray = (int*)malloc(count*sizeof(int));
if (myarray == NULL)
return -1;
for(int i = 0;i<count;i++)
{
myarray[i]=array[i];
}
return count;
i think maybe it forgets to use free() after using the malloc() function to free the memory but this code is meant to copy array element in the memory.so whether i am right ? If no, what is the really bug?
This function leaks memory.
myarray contains a pointer to allocated memory which contains a copy of the data in array. However, this pointer is not used in any way when the function returns so the pointer to the allocated memory is lost.
The function should return a pointer to this memory so that it can be used.
int *copy(int *array ,int count){
int i;
int *myarray = malloc(count*sizeof(int));
if (myarray == NULL)
return -1;
for(int i = 0;i<count;i++)
{
myarray[i]=array[i];
}
return myarray;
}
Note that it will be the responsibility of the calling function to free the memory when it is done with it.
Your copy function functions allocates memory and then copies the elements of the array to that newly allocated memory. So far so good, but then you simply throw away the pointer to that newly allocated memory.
It's like copying a letter by hand, putting the copy into a safe, closing the safe with the key and then throw the key away. Now the copy of the letter is in the safe, but you can't access it any more.
You probably want something like this:
...
int *copy(int *array, int count) // return a pointer to int, not an int
{
int *myarray = malloc(count*sizeof(int)); // (int*) cast is not needed
if (myarray == NULL)
return NULL; // return NULL if malloc fails
for(int i = 0; i < count; i++)
{
myarray[i] = array[i];
}
return myarray; // return pointer to newly allocated memory
}
...
int source[] = {1,2,3,4,5};
int *destination = copy(source, 5);
if (destination == NULL)
{
// handle error
}
// now destination points the the copy of the array
for (int i = 0; i < 5; i++)
{
printf("%d\n", destination[i]);
}
...
free(destination); // free allocated memory when you're done with it
...
My program takes an arbitrary number of words at runtime and stores them in a dynamically-sized array of words.
Currently, my program runs well, except when I use free() to free up the memory of the temporary double pointer temp. I am not quite sure why it does this, as I thought it would cause errors if I didn't use it.
int wordSize = 10, arrSize = 1, i = 0;
char **stringArr, **temp;
char *input;
stringArr = malloc(arrSize * sizeof(char *));
puts("Accepting input...");
for (;;) {
if (i >= arrSize) {
arrSize += 1;
temp = realloc(stringArr, arrSize * sizeof(char *));
if (temp != NULL) {
stringArr = temp;
free(temp); // This is the line that is giving me issues; removing it works
} else {
puts("Could not allocate more memory");
return 0;
}
}
stringArr[i] = malloc(sizeof(input));
input = malloc(wordSize * sizeof(char));
scanf("%10s", input);
if (strcmp(input, "END")) {
strcpy(stringArr[i], input);
i++;
} else
break;
}
free(stringArr);
At the bottom of my program I use free() without any issues. How come it works OK here but not earlier on in the program.
I feel I am missing something about how free() works.
Note: this is my first program implementing malloc() and realloc(), so I am only just getting used to how they work. If you know of a better way to accomplish what I am doing that, please feel free to describe.
The free(temp); line is causing an error (later on) because, in the preceding line, stringArr = temp;, you are assigning the address that is stored in the temp pointer to that in the stringArr pointer. Thus, when you free the memory pointed to by temp you also free the memory pointed to by stringArr, because it is the same memory block. Copying a pointer's value from one variable to another does not make a (separate) copy of the memory.
Omitting the free(temp); line is correct, because that memory is freed later on, in the free(stringArr); call.
You must not free the reallocated array when reallocation was successful. If you do that, the code will modify this freed block, which has undefined behavior and you will have further undefined behavior when you later try and reallocate or free this block.
Note also the following:
pre-allocating stringArr with a size of 1 is not necessary. Just initialize stringArr to 0 and arrSize to 0. realloc() can take a null pointer and will behave like malloc().
stringArr[i] = malloc(sizeof(input)); is incorrect: it will allocate a char array with a size of 4 or 8 depending on the size of a pointer on the target architecture, not 11 bytes as it should.
if the wordSize is the maximum length of a word, you should allocate one more byte for the null terminator. The 10 in %10s must match the value of wordSize, which is cumbersome because there is no easy way to pass this to scanf() as a variable.
you do not check the return value of scanf(), causing undefined behavior in case of premature end of file.
you have memory leaks: input is allocated for each iteration but never freed, freeing stringArr without freeing the strings pointed to by its elements makes them inaccessible.
It would be more efficient to use a local array to try and read the words with scanf() and only allocate the string and reallocate the array if successful.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int arrSize = 0;
char **stringArr = NULL;
char input[11];
puts("Accepting input...");
while (scanf("%10s", input) == 1 && strcmp(input, "END") != 0) {
char **temp = realloc(stringArr, (arrSize + 1) * sizeof(*stringArr));
if (temp != NULL) {
stringArr = temp;
} else {
puts("Could not allocate more memory");
break;
}
stringArr[arrSize] = strdup(input);
if (stringArr[arrSize] == NULL) {
puts("Could not allocate more memory");
break;
}
arrSize++;
}
puts("Array contents:");
for (int i = 0; i < arrSize; i++) {
printf("%i: %s\n", i, stringArr[i]);
}
for (int i = 0; i < arrSize; i++) {
free(stringArr[i]);
}
free(stringArr);
return 0;
}
As I ask how can I read values from the memory which was put into a memory block by malloc/realloc?
I have a program which creates 2 memory blocks at first and extends until reach 32.Its working fine but in order not to lose values after realloc I start my scanf session with an integer called koru.Koru starts with 0 at the beginning and in every realloc I make its number half of the total amount of memory so I expect not to lose the values entered before realloc sessions but now I need to read what I wrote the memory so I will be sure that I didnt overwrite how can I do that ?
#include "stdio.h"
#include "stdlib.h"
int main()
{
int size=2;
int* p1;
int* p2;
int n;
p1=(int *)malloc((size*sizeof(int)));
int b=0;
int i=0;
int koru=0;
while(size<32)
{
if(i<size){
for(i=koru;i<size;i++)
{
printf("\nEnter value:");
scanf("%d",p1);
}
}
else if(boyut=i)
{
size=size*2;
p2 = (int*) realloc (p1,size*sizeof(int));
p1=p2;
koru=size/2;
printf("\nNOt enough size we make it %d also we protect %d that amount of memory"size,koru);
}
}
return 0;
}
I thought putting a array[i]=p1; and reading it after while loop will solve the problem but later I figured out that its cheating I am not reading from the memory block just reading from another array so this wont work too can somebody lead the way for me please ?
What my program does:
2 blocks memory malloc
takes values and fills it
When it fills improves the memory size multiplying by 2 realloc
starts reading from half number so it dont rewite
continues this progress until it reaches 32
Edit:Simplified question:
I put lots of values in the memory after while loop how can I read them ?
I tried to read it like this but all I get is 0
int counter =0;
while (counter<koru)
{
printf("\n%d",p1[counter]);
counter++;
}
return 0;
}
The correct code which creates a memory block with malloc and extends it with realloc after 32 it exits while loop and writes everything from the p1 pointer(from memory) thanks for help.
Working Code below:
#include "stdio.h"
#include "stdlib.h"
int main()
{
int boyut=2;
int* p1;
int* p2;
int n;
p1=(int *)malloc((boyut*sizeof(int)));
int b=0;
int i=0;
int koru=0;
while(boyut<16)
{
if(i<boyut){
for(i=koru;i<boyut;i++){
printf("\nDeğer Girin:");
scanf("%d", &p1[i]);
}
}
else if(boyut=i)
{
boyut=boyut*2;
p2 = (int*) realloc (p1,boyut*sizeof(int));
p1=p2;
koru=boyut/2;
printf("\nBoyut yetersiz yeni boyutu %d yapıyoruz önceki %d kadar alanı korumaya aldık",boyut,koru);
}
}
int counter =0;
while (counter<koru)
{
printf("\n%d",p1[counter]);
counter++;
}
return 0;
}
I'm not sure exactly what you are asking here, but to access the values in the memory, just use p1 as an array. p1[3] would give you the 4th integer in the memory block.
Just be sure to respect the array bounds.
Bonus problem: you're not even filling the array, you're overwriting the first element each time you input.
The simple solution is to remove p2 entirely and treat p1 as an array:
...
scanf("%d", &p1[i]);
...
Then to read:
int n;
for (n=0; n<i; n++)
printf("%d ", p1[n]);
However, if you want to do it with two pointers instead of array indexing, you need one pointer to track the whole array for malloc and realloc, and the other to track where the current value is for reading/writing.
Initially the array is empty, so they are the same:
p1 = (int *)malloc(boyut * sizeof(int));
p2 = p1;
...
Input only uses the read/write pointer, and increments it each time:
...
scanf("%d", p2++);
...
Memory management only uses the "base" pointer
...
p1 = (int *)realloc(p1, boyut * sizeof(int));
...
(note you should strictly use a temporary variable for the return value of realloc() to check for failure, otherwise you could lose the value of p1)
Then to read we reset the read/write pointer to the start, and iterate through:
int n;
p2 = p1;
for (n=0; n<i; n++)
printf("%d ", *p2++);
So I wrote this code but it gives me the same answer everytime. I am increasing the memory allocated to the pointer in steps of 4 and then print the value.
#include <stdio.h>
int main(void) {
int n=0;
char *name = "hello";
scanf("%d",&n);
for(int i =0; i<n;i++){
name += sizeof(int);
printf("%d \n", (sizeof(&name)));
}
return 0;
}
can someone help me? I don't know whats wrong here. I don't need a different code, I just want to understand what's wrong with this.
Try the following, error checking was left out for clarity:
#include <stdio.h>
int main(void)
{
int n=0;
char *name = null;
scanf("%d",&n);
for(int i=0; i<n;i++)
{
char *buffer = null;
//allocate/reallocate the buffer. increases by 4 bytes every iteration
buffer = (char*) realloc(name, (i+1)*4);
name = buffer;
printf("%d \n", (sizeof(&name)));
}
//release the memory used by the buffer
free(name);
return 0;
}
Here are some explanations of what is happening.
#include <stdio.h>
int main(void) {
int n=0;
// this does not actually allocate any memory. It sets the POINTER name to point (like an arrow) to a read-only block that contains "hello"
char *name = "hello";
// string literals generally come in fixed read-only memory
scanf("%d",&n);
for(int i =0; i<n;i++){
// this causes the pointer memory address to be incremented by sizeof(int) (typically 4)
// after the first increment if it will point to a string "o" (incremented by 4 characters)
// after the second increment it will point to some undefined memory behind "hello" in your virtual address space and will have undefined behaviour when accessed
name += sizeof(int);
// sizeof(&name) will give you the size of a char **. Pointer to a character pointer.
// Wich is the same size as all pointers.
// = sizeof(void *) = 8 for 64-bit systems, 4 for 32-bit systems
printf("%d \n", (sizeof(&name)));
}
return 0;
}
This is the way to do it:
#include <stdio.h>
int main(void) {
int n=0;
// allocate 10 bytes of memory and assign that memory address to name
char *name = malloc(10);
// the size of that memory needs to be kept in a separate variable
size_t name_length = 10;
// copy the desired contents into that memory
memcpy(name, "hello", sizeof("hello"));
scanf("%d",&n);
for(int i =0; i<n;i++){
// reallocate the memory into something with sizeof(int) more bytes
void * tmp = realloc(name, name_length += sizeof(int));
// this can fail
if (tmp) {
name = tmp;
} else {
perror("realloc");
exit(-1);
}
printf("%d \n", name_length);
}
return 0;
}
You have not allocated any memory for the pointer at all in the code you provide. You will have to deal with dynamic memory if you want to change the size of the allocated chunk. You will have to initially use malloc and then use realloc to allocate more memory on each step.
Let's step through your code one by one:
char *name = "hello";
this create an array of chars 'h','e','l','l','o',0 and assignes the memory address of the first character to name
for(int i =0; i<n;i++){
name += sizeof(int);
printf("%d \n", (sizeof(&name)));
}
here you add to the name pointer the size of int, which increments this pointer by 4 each pass.
Since this is a char pointer, the pointer is incremented by 4 bytes - since sizeof(int) == 4
You cannot increase the size of your hello char array, since it is not a dynamic array.
If you wish to be able to resize the string, you should malloc and copy the chars to the bigger array.
The following C code returns a "segmentation fault" error. I do not understand why it does not return the value 20. What is my error?
#include <stdio.h>
int main()
{
int* n;
*n = 20;
printf("%i\n",*n);
return 0;
}
You haven't allocated memory to n, so
*n = 20;
attempts to write unspecified memory.
Try
#include <stdlib.h>
int *n = malloc(sizeof *n);
/* use n */
free(n);
You haven't allocated space for your int, you've only declared a pointer to an int.
The pointer is uninitialized, and so writing to that unknown space in memory is undefined behavior and causes problems. This typically causes a segfault.
You can allocate a slot for an integer using malloc:
n = malloc(sizeof(int));
And use a corresponding call to free to free up the memory later:
free(n);
But allocating a single slot for an integer is pretty unusual, typically you would allocate the int on the stack:
int n;
n = 20;
You are trying to write 20 in garbage value. You must allocate space for it by using one of *alloc() functions or creating an int on stack and getting the andress of it(as Richard J. Ross III mentioned on comments).
dynamic allocation:
int n*;
n = malloc(sizeof(int)); /* allocate space for an int */
if(n != NULL) {
/* do something.. */
free(n); /* free 'n' */
} else {
/*No space available. */
}
or on the stack:
int int_on_stack;
int *n = &int_on_stack;
*n = 20;
printf("%i\n", *n); // 20