Reputation: 77
I am learning about dynamic memory allocation and having a problem while doing the exercise. I would like to allocate the memory for p. The following is the codes.
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int *p, i;
p = (int *)malloc(7 * sizeof(int));
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<6; i++)
{
p++;
*p = i;
printf("%3d",*p);
}
printf("\n");
p = p - 6;
free(p);
p = NULL;
return 0;
}
The running result is:0 1 2 3 4 5
However, when I change the code
p = (int *)malloc(7 * sizeof(int));
to this
p = (int *)malloc(6 * sizeof(int));
the running result would be
0 1 2 3 4 5
Error in `./memo2': free(): invalid next size (fast): 0x0000000001bc5010 ***
Aborted (core dumped)
I think for this code, p only need the memory of the size of 6 integers, could anyone give a explanation?
Another question is that why should p++
be ahead of *p = i
? If I make *p = i
before p++
, the running result would be 0 0 0 0 0 0
.
Upvotes: 1
Views: 2695
Reputation: 6067
Try this.
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int *p, i;
p = malloc(7 * sizeof(int)); /* Memory allocated for 7 intergers */
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<=6; i++) /* Assign values */
{
// This is a better way of assignment, easy to understand
// *(p+i) = i OR p[i] = i
p[i] = i;
printf("%3d",p[i]);
}
printf("\n");
// p = p - 6; /* Not required */
free(p); /* Free the pointer */
// p = NULL; /* Not required */
return 0;
}
The output will be:
0 1 2 3 4 5 6
Upvotes: 1
Reputation: 3870
1) When you do like this
for(i=0; i<6; i++)
{
p++; // here before assigning the value you are incrementing address of p(first location is waste)
*p = i;
printf("%3d",*p);
}
So it does not store value in first memory location(this location is wasted). it stores value from second location on wards. so it requires 7 location for 6 numbers.
2) If you make *p = i
before p++
, like below code-
for(i=0; i<6; i++)
{
*p = i; // you are assigning the value.
p++; // here you are incrementing the value
printf("%3d",*p); // it will print the value at the incremented loaction
}
For example- Consider starting address is 1000. when you do *p = i;
i is assigned to 1000, p++;
will increment the location to 1004. After incrementing the address you are printing the value. It may give you 0
or garbage values
. because printf("%3d",*p);
will print the value at 1004. you don't know what value is there. So avoid this types of method.
Try the following code-
p = (int *)malloc(6 * sizeof(int)); // Fix 1
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<6; i++)
{
*p = i;
printf("%3d",*p);
p++; // Fix 2
}
printf("\n");
p = p - 6;
free(p);
p = NULL;
Upvotes: 1
Reputation: 92404
Your code needs 7 "slots" to store 6 numbers because the very first slot is immediately skipped:
for(i=0; i<6; i++)
{
p++; // <-- Skip to next "slot"
*p = i;
printf("%3d",*p);
}
So the first slot is never used since it's immediately skipped. To fix this, first work with the current pointer, then increment it:
p = malloc(6 * sizeof(int));
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<6; i++)
{
*p = i;
printf("%3d",*p);
p++; // <-- Skip to next "slot"
}
Also, the pointer you pass to free
must be exactly the same pointer you got from malloc
. You can calculate the original value by undoing the additions you did in a loop, but it's easier to store the original value (less chance to screw up):
int *p, *orig_p, i;
orig_p = malloc(6 * sizeof(int));
if (orig_p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
p = orig_p;
...
free(orig_p);
Upvotes: 3
Reputation: 1769
First question - you get an error when you malloc
memory for 6 integers because in your for
loop you increment the pointer before assigning a value. Therefore you leave the first address you allocated empty. If you assign a value and then increment the pointer this will solve your problem.
Second question - if you perform the printf
after incrementing the pointer you won't print the value you just set. You need to assign the value, print it, then increment the pointer.
Here's your code with those changes:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int *p, i;
p = (int *)malloc(6 * sizeof(int));
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<6; i++)
{
*p = i;
printf("%3d",*p);
p++;
}
printf("\n");
p = p - 6;
free(p);
p = NULL;
return 0;
}
However, I would recommend you use array indexing syntax. As well as being easier to read, this means that you don't actually change the p
meaning that when you free
the memory it will be on the correct address. Here's an updated version of your code using array indexing:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int *p, i;
p = (int *)malloc(6 * sizeof(int));
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<6; i++)
{
p[i] = i;
printf("%3d",p[i]);
}
printf("\n");
free(p);
p = NULL;
return 0;
}
Upvotes: 3
Reputation: 1323
For your subquestion2, find the answer in below
for(i=0; i<6; i++)
{
*p = i;
printf("%3d",*p); //Fix1
p++; //Fix2
}
ie,you should print the value *p before increment the pointer p.
Upvotes: 1
Reputation: 182865
You have p
, that's one slot. Then you increment p
six times, that's six more slots. So you need seven slots in total.
Upvotes: 0