Program 3

advertisement
Common errors in memory allocation and free
//Program to dump the memory content
#include <stdlib.h>
#include <stdio.h>
void main(){
char *ptr, *ptr1;
ptr = (char *)malloc(16 * sizeof(char)); //allocate 16 bytes;
int *ptr2;
ptr2 = (int *)malloc(4* sizeof(int)); //allocate 4 x 4 = 16 bytes, not 4 bytes
ptr1 = ptr;
*ptr++ = 'C'; //note the pointer is incremented by one after this operation
*ptr++ = 'I';
*ptr++ = 'T';
*ptr++ = 'Y';
*ptr++ = 'U';
*ptr = 0x00; //terminator, null
printf("The string is %s\n", ptr1); //note that ptr is
// on longer pointing to CityU; but 0x00,
*ptr2 = 12345;
printf("The value is %d and address is %d\n", *ptr2, ptr2);
free(ptr1); //free pointer1 not ptr, as ptr points to 0x00
free(ptr2); //free pointer
}
The number of bytes allocated to pointer, ptr; is 16 (CD CD CD……..)
After allocating one byte *ptr++ = 'C'; you can see the content is changed
2016/3/7
1
Up to here, you might wander why there are two pointers. Since we are incrementing
the pointer to point to next character, the original location is lost. That is why we need
to keep it. Another question you might ask. Why there is a 0x00? It is used to indicate
that this is the end of string.
After the executing the free(ptr2); you will find that DD DD DD….. are used to fill in
the memory.
2016/3/7
2
The integer 12345 (dec) (0x003039 in hex) is shown below. Note that it allocates 16
bytes (4 integers) and this just use the first integer only.
2016/3/7
3
Program 2: structure and pointer
#include <stdlib.h> // include file for malloc() system call
void main(){
typedef struct {
int int_field;
double dbl_field;
} my_struct_type;
// allocate a structure on the heap
my_struct_type *s;
s = (my_struct_type *) malloc(sizeof(my_struct_type));
// 16 bytes, 4 for integer, 4 (dummy) and 8 bytes for double
// initialize fields of s
s->int_field = 0;
s->dbl_field = 0.0;
}
In the above, you will find that CD CD CD CD are used due to alignment. The integer
is initialized to 0x00 00 00 00 (o in decimal) and occupies 4 bytes.
Three structure
#include <stdlib.h> // include file for malloc() system call
void main(){
typedef struct {
2016/3/7
4
int int_field;
double dbl_field;
} my_struct_type;
// allocate three structures on the heap
my_struct_type *s;
s = (my_struct_type *) malloc(3*sizeof(my_struct_type));
// 16 bytes, 4 for integer, 4 (dummy) and 8 bytes for double
// initialize fields of s
s->int_field = 0;
s->dbl_field = 0.0;
s++; //next structure
s->int_field = 1; //
s->dbl_field = 1.0;
s++; //next structure
s->int_field = 2; //
s->dbl_field = 1.0;
}
0x00780e90 is the pointer to s. It will point to the first structure. If we increase s by
one, it will point to the next block, 0x00780eA0. The difference between 0x90 and
0xA0 is the size of structure.
2016/3/7
5
Program 3
#include <stdlib.h>
#include <stdio.h>
void mult_array_by_scalar(double x[], int n, double y)
{
double *ptr = x; // point to first element in x
for (int i = 0; i < n; i++) {
*ptr++ *= y;
}
}
void main(){
double z[5] = {1, 2, 3, 4, 5};
int i =5;
double j = 2.0;
mult_array_by_scalar(z, i, j); //pass the address of z
// you can define x[] and pass x
for (i = 0; i <5; i++)
printf("the value of %d is %3f\n", i, z[i]);
}
2016/3/7
6
Note that when pointer is incremented by one ptr++, it will be incremented by 8 bytes.
Please note the following address after pressing “F10”. Please note that the storage is
in double, so you might find it difficult to understand the meaning 00 40.
2016/3/7
7
Program 4
#include <stdlib.h>
#include <stdio.h>
int sum(int a[], int n)
{
int *p;
int sum = 0;
for (int i = 0; i < n; i++)
sum += *p++;
return sum;
}
void main(){
int z[5] = {1, 2, 3, 4, 5};
int i =5;
int sum1 = sum(z, i);
printf("the value of sum is %d\n", sum1);
}
It causes the system crashes as shown above, as the pointer is not properly initialized.
Now, look at the following program with modification.
#include <stdlib.h>
#include <stdio.h>
2016/3/7
8
int sum(int a[], int n)
{
int *p = a; // assign the address
int sum = 0;
for (int i = 0; i < n; i++)
sum += *p++;
return sum;
}
void main(){
int z[5] = {1, 2, 3, 4, 5};
int i =5;
int sum1 = sum(z, i);
printf("the value of sum is %d\n", sum1);
}
The above program has been modified with the following:
int *p = a; // assign the address
the pointer is now pointing to an integer array.
It will print out the result correctly.
Program 5
2016/3/7
9
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(){
char q[] = "do not overflow";
char r[] = " memory";
char s[16];
strcpy(s, q); //copy string q to string s
strcat(s, r); //add strings s and r together and put it back to s
printf("The string is %s\n", s);
}
You might ask why it will print out the string correctly.
As s[16] bytes only and “do not overflow” already occupies 16 bytes. The reason is
that “do not overflow “ occupies the 16 bytes followed by “memory” terminator. The
command will overwrite the string including the terminator followed by memory with
a terminator. That is why it looks like it works. In fact, it should not
strcpy(s, q);
2016/3/7
10
16 bytes from
0065fdd0
Terminator 0x00
After pressing F10, note that overlaps with “memory” + 0x00. Press F10 again, it
overwrites the r[] string.
2016/3/7
11
Now modify the program to print out r, s and q. You will
find that r and q were corrupted. Note that I have extended the size of s.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(){
char q[] = "do not overflow";
char r[] = " memory";
char s[19]; //extend the size
strcpy(s, q);
strcat(s, r);
printf("The string s is: %s\n", s);
printf("The string q is: %s\n", q);
printf("The string r is: %s\n", r);
}
As the string s has extended to the string q, that is why r string has been reduced. You
can dump the memory and notice that the terminator has been added.
Program to return an undefined value
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int *ptr_to_zero()
{
int i = 0;
return &i;
//integer is a local variable and is put on stack, this returns
// an undefined variable.
}
2016/3/7
12
void main() {
int *ptr;
ptr = ptr_to_zero();
printf("The valus is %d\n", *ptr);
}
Program to show free twice
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main() {
int *ptr = (int *) malloc(4*sizeof(int)); //allocate 16 bytes;
*ptr = 1234;
printf("The valus is %d \n", *ptr);
free(ptr); // free this pointer
printf("The valus is %d \n", *ptr);
free(ptr); //free it again
printf("The valus is %d \n", *ptr);
}
2016/3/7
13
It shows that the system crash as it cannot return the pointer to the system properly
once it has been freed.
Program that forgets to free other memory location
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char *name;
int age;
char *address;
int phone;
} Person;
void main()
{
int M= 20, N= 20;
Person *p = (Person *) malloc(sizeof(Person));
p->name = (char *) malloc(M);
p->name = "Chan Tai Man";
p->age = 18;
p->address = (char *) malloc(N);
p->address = "No1 Nathan Road";
2016/3/7
14
free(p); // it free p. However, what about name and address, which is also a
//pointer. We should free(name) and free(address) before free(p).
}
Name Not free
Only free the p, not the content
2016/3/7
15
Download