Monday, 26 August 2013

MEMCPY AND MEMMOVE

#include <string.h>
#include <stdio.h>
#include<stdlib.h>
 int main()
 {

  char a[20]="vinayagam";
  char b[20]="vinayagam";
 printf("Address of A:%u",&a);
 printf("Address of B:%u",&b);
  memmove(a+5, a, 20);
   puts(a);
 memcpy(b+5, b, 20);
   puts(b);
   }
The output:

Address of A:2815980

Address of B:2815952.
vinayvinayagam
vinayvinayagam


In this program memmove handles the overlapping of source and destination,But memcpy doesn't

able to handle the overlapping of souce and destination strings.So buffer over run occurs at 'b'.

 

Reason For Not working:


Normally, a memcpy that copies downwards(Downwards means source address will be higher than destination address Ex:memcpy(0x20,0x50,30) will work

perfectly well in practice, because the natural way to do memcpy() by making it just copy things upwards will  just work even for the overlapping case but causes buffer overflow.


To Avoid Overlapping in memcpy:


We can use memcpy in the case of downwards:

Ex:
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
 int main()
 {

  char a[20]="vinayagam";
  char b[20]="vinayagam";
 printf("Address of A:%u",&a);
 printf("Address of B:%u",&b);
  memmove(a+5,a,9);
   puts(a);
 memcpy(b,b+5,4);
   puts(b);
   }

The output:

Address of A:2815980

Address of B:2815952.

vinayvinayagam
agamyagam


 

STRCPY VS MEMCPY

Strcpy:

Strcpy deals with arrays of characters ending in \0.It will fail horribly if there is no '\0'.

On the other hand the syntax of strcpy is:

char *strcpy(char *s1, const char *s2);

s1-destination string.

s2-source string.

It will copy the string pointed by s2 into s1.

While copying is there any overlapping occures means its performance is undefined.

The disadvantage of strcpy is, It doesn't perform Bounds Checking(Setting or Verifying the size of data before storing the data into the Buffers).

For Example:

#include <stdio.h>
#include <string.h>
int main()
 {
    char buf[4]= "";
    char sun[12]= "how are you";
    strcpy(buf, sun);  
    printf("%s\n", buf);
    return 0;

 }

In the above program The size of the source is high compared to size of the destination.

So While debugging Buffer overflow occurs.

We choose alternative Function like memcpy which perform Bound checking.We can consider strncpy() also.


Memcpy:

The Syntax of Memcpy is

void *memcpy(void*dest,const void* src,int n)

dest-destination buffer.

src-source buffer.

In that n defines the number of bytes to be transferred.
Example:

#include <stdio.h>
#include <string.h>
int main()
 {
    char buf[4]= "";
    char sun[12]= "how are you";
    memcpy(buf, sun, 4);  
    printf("%s\n", buf);
    return 0;

 }

In the above program only 4 bytes of data can be transfered to buf from sun.

So with the help of this memcpy we can avoid buffer overflow.

But the disadvantage of memcpy is when overlapping between source and destination occurs

means it also made buffer overflow while debugging.It does n't copy the data safely before overlapping.

That problem can be solved with the help of memmove function.

 

The other difference between strcpy and memcpy is explained below the program:

#include <stdio.h>
#include <string.h>

int main()
{
  char s1[10] = "abc\0def";
  char s2[10] = "";
  char m1[10] = "abc\0def";
  char m2[10] = "";
  int i;

  strcpy(s2,s1);
  for(i=0;i<10;i++)
  {
  printf("STRCPY %d= %c\n",i,s2[i]);
}

  memcpy(m2,m1,10);
  for(i = 0; i <10; i++)
    {
      printf("MEMCPY %d - %c\n", i, m2[i]);
    }

  return 0;
}
The Output of the above program is:

STRCPY 0= a
STRCPY 1= b
STRCPY 2= c
STRCPY 3=
STRCPY 4=
STRCPY 5=
STRCPY 6=
STRCPY 7=
STRCPY 8=
STRCPY 9=
MEMCPY 0 - a
MEMCPY 1 - b
MEMCPY 2 - c
MEMCPY 3 -
MEMCPY 4 - d
MEMCPY 5 - e
MEMCPY 6 - f
MEMCPY 7 -
MEMCPY 8 -
MEMCPY 9 -

So in the above result the function strcpy copy the contents until it finds '\0'(NULL)character.

But memcpy copies the content without considering the NULL termination.

 

Strcpy with integers:


#include<stdio.h>
#include<string.h>
int main()
 {
 int dst[3]={60,90,50};
 int src[3]={30,25,35};
 strcpy((char *)dst,(char *)src);
 for(int i=0;i<3;i++0
  {
  printf("dst=%d\n", dst[i]);
  }

 }

The output is:

dst=30
dst=90
dst=50


Even we use type casting for integers it won't workout in strcpy.Because size of the integers and charcters are different.

 

So The other thing which makes variation between strcpy()and memcpy() is, memcpy() is adaptable for both characters and strings.

strcpy() is adaptable only for strings.

 

 

 

 


 

STRUCTURE PADDING

Structure alignment:

 The Structure alignment for 32 bit machine will be in either increasing/decreasing order.

 

Ex:

Typical Structure alignment

Struct tag

{

char  c;       //1byte

short int d;   //2bytes

int   e;       //4bytes

double f;      //8bytes

};

Structure Padding:

 In order to align the data in memory,  one or more empty bytes(addresses) are inserted (or left empty) between memory addresses

which are allocated for other structure members while memory allocation. This concept is called structure padding.

Why Structure Padding?

 Architecture of a computer processor is such a way that it can read 1 word (4 byte in 32 bit processor) from memory at a time.

To make use of this advantage of processor, data are always aligned as 4 bytes package which leads to insert empty addresses between other member’s address.

 

Because of this structure padding concept in C, size of the structure is always not same as what we think.

 

Ex:

struct structure1

 {

       short int id;

       char name[20];

       char c;

       long percentage;

       double marks;

 };

 

We thing that the size of structure becomes (short int)2 bytes+(char name[20])20 bytes+(char c)1 byte+(long percentage)4 bytes+(double marks)8 bytes=35 bytes.

 

But the actual size of the structure given by compiler is 40  bytes Because of structure padding.

Padding done as follows:

2 Bytes+2 Bytes(padding)+20 bytes+1 byte+3 bytes(padding)+4 bytes+8 bytes=40 Bytes.

If we change the alignment of Structure Like below means:

struct structure2

 {

 char c;

 long percentage;

 short int id;

 double marks;

 char name[20];

 };

Then the size of the structure becomes

1byte+3bytes(padding)+4bytes+2bytes+6bytes(padding)+8bytes+20bytes=44 bytes.

So If we align the structure in an order means

struct structure1

 {

       char c;

       short int id;

       long percentage;

       double marks;

       char name[20];

 };

Then the size of the structure becomes

1 byte+2bytes+1byte(padding)+4bytes+8bytes+20bytes=36bytes.

 

So if we aligned a structure in an order(in this example increasing)means we got the size of the structure minimum.

How to avoid Structure padding?

1.By proper aligning of structures we can avoid structure padding.

2.we can also use #pragma pack(1)Function to reduce the structure padding.

 

#pragma pack(n):

The purpose of #pragma pack is to Sets the alignment of all aggregate members to a specified byte boundary.

Here n is the alignment in bytes, valid alignment values being 1, 2, 4 and 8.

So if we use #pragma pack(1) means we can get the size of the structure as 35 bytes as what we have calculate.

But, If we use #pragma pack() The speed of the processor becomes slow.Because the processor align the members by padding bytes(According to word length of processor) to get high speed.

If we use pragma means at compiler or processor point of view the members are misaligned. So for accessing those members

we require more coding's which leads to PERFORMANCE PENALTY.

 

Then NEED OF #pragma pack:

We use pragma pack only when our structure match an exact data layout. Ex: Networking protocols and device drivers accessing HW registers.

Linked list Vs Array

Linked list and array:
Linked list and array are same to store the collection of data.
But the difference is array only store the same type of Data. Linked List store the different kinds of data using structures.
Structures are used to create a collection of data with different types.


The Disadvantage of using array is we can initially declare the array[100].
It means at compile time it will be allocated for 100 blocks.
But most of the time we use only 20 to 30 blocks of array.
So that the remaining memory spaces are wasted.
For recovering this we need to initialize the array dynamically at runtime.
That is done with the help of malloc() function and Pointers