Question regarding memcpy and memmove function

S

somenath

Hi All,
I am trying to understand the behavior of the memcpy and memmove.
While doing so I wrote a program as mentioned bellow .

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

#define SIZE_OF_DST 3
int main(void)
{
char src[]="somenath";
char *dest = malloc(SIZE_OF_DST * sizeof(*dest));
if(dest)
{
memcpy(dest,src,SIZE_OF_DST -1 );
src[SIZE_OF_DST]='\0';
printf("\n Source = %s Destination = %s \n", src,dest);

}
else
{ /*Memory allocation failled */
printf("\n Not enough Memory \n");

}
return 0;
}

Source = som Destination = so

1) But I am not able to understand why "src[SIZE_OF_DST]='\0' " is
affecting the source string?
2) If I remove the "src[SIZE_OF_DST]='\0'" it produce the output as
mentioned as bellow

Source = somenath Destination = so
Please help me to understand this.

I have another couple of questions

1) how "memmove" works for overlapping objects ?
2) Why the behavior of memcpy is undefined for overlapping objects?

3) Is it possible to write strcpy function for overlapping object ?
If yes what would be the logic

..
Regards,
Somenath
 
I

Ian Collins

somenath said:
Hi All,
I am trying to understand the behavior of the memcpy and memmove.
While doing so I wrote a program as mentioned bellow .

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

#define SIZE_OF_DST 3
int main(void)
{
char src[]="somenath";
char *dest = malloc(SIZE_OF_DST * sizeof(*dest));
if(dest)
{
memcpy(dest,src,SIZE_OF_DST -1 );
src[SIZE_OF_DST]='\0';
printf("\n Source = %s Destination = %s \n", src,dest);

}
else
{ /*Memory allocation failled */
printf("\n Not enough Memory \n");

}
return 0;
}

Source = som Destination = so

1) But I am not able to understand why "src[SIZE_OF_DST]='\0' " is
affecting the source string?

Because you told it to? The dest output is pure luck as you didn't
terminate it.
2) If I remove the "src[SIZE_OF_DST]='\0'" it produce the output as
mentioned as bellow

Source = somenath Destination = so
Please help me to understand this.
because you didn't change it.
I have another couple of questions

1) how "memmove" works for overlapping objects ?

Possibly by starting form the last byte and working back. Look for one
on many implementations on the web.
2) Why the behavior of memcpy is undefined for overlapping objects?
Possibly because it makes it easier to optimise, memmove an be used for
overlapping regions
3) Is it possible to write strcpy function for overlapping object ?
If yes what would be the logic
Probably, give it a go and see whet you come up with (hint see 1).
 
K

Keith Thompson

somenath said:
I am trying to understand the behavior of the memcpy and memmove.
While doing so I wrote a program as mentioned bellow .

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

#define SIZE_OF_DST 3
int main(void)
{
char src[]="somenath";
char *dest = malloc(SIZE_OF_DST * sizeof(*dest));
if(dest)
{
memcpy(dest,src,SIZE_OF_DST -1 );
src[SIZE_OF_DST]='\0';
printf("\n Source = %s Destination = %s \n", src,dest);

}
else
{ /*Memory allocation failled */
printf("\n Not enough Memory \n");

}
return 0;
}

Source = som Destination = so

1) But I am not able to understand why "src[SIZE_OF_DST]='\0' " is
affecting the source string?
2) If I remove the "src[SIZE_OF_DST]='\0'" it produce the output as
mentioned as bellow
Source = somenath Destination = so
Please help me to understand this.

Looks like a simple typo. Rather than
src[SIZE_OF_DST]='\0';
I think you meant
dest[SIZE_OF_DST]='\0';

In your program as posted, with or without the assignment to
src[SIZE_OF_DST], the string in 'dest' isn't necessarily terminated by
a '\0'. There was probably a zero byte there by chance.
I have another couple of questions

1) how "memmove" works for overlapping objects ?

It works as specified. It's equivalent to copying the source to some
separate location, then copying from that location to the destination.
In practice, the usual way to do this is to copy the bytes in reverse
order when that's necessary to get the right result. Determining when
it's necessary (i.e., detecting overlap) isn't something that can
easily be done in portable code, but the implementation is free to use
non-portable tricks (such as, perhaps, comparing pointers to different
objects using said:
2) Why the behavior of memcpy is undefined for overlapping objects?

It's to allow memcpy() to be done efficiently for non-overlapping
objects. A straightforward implementation of memcpy can fail if the
objects overlap; a version that detects overlap and works around it is
less efficient (that's just what memmove is for).
3) Is it possible to write strcpy function for overlapping object ?
If yes what would be the logic

I suppose it would be, but there doesn't seem to be much need for it.
Two strings can overlap only if one is a trailing substring of the
other, such as "hello\0" and "ello\0" (I've made the '\0's explicit
for emphasis), and you could only copy the shorter one to the longer
one. In effect, the only use would be to delete the first N
characters of a string. If you really need to do that, you can
compute the offsets and sizes and use memmove -- or, in many cases,
advancing the pointer may be good enough.
 
A

Army1987

Hi All,
I am trying to understand the behavior of the memcpy and memmove.
While doing so I wrote a program as mentioned bellow .

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

#define SIZE_OF_DST 3
int main(void)
{
char src[]="somenath";
char *dest = malloc(SIZE_OF_DST * sizeof(*dest));
if(dest)
{
memcpy(dest,src,SIZE_OF_DST -1 );
src[SIZE_OF_DST]='\0';
printf("\n Source = %s Destination = %s \n", src,dest);

}
else
{ /*Memory allocation failled */
printf("\n Not enough Memory \n");

}
return 0;
}

Source = som Destination = so

1) But I am not able to understand why "src[SIZE_OF_DST]='\0' " is
affecting the source string?

Because src is the source string. You meant dest[SIZE_OF_DST]?
2) If I remove the "src[SIZE_OF_DST]='\0'" it produce the output as
mentioned as bellow

Source = somenath Destination = so

Because dest[3] was already 0. It is very common, but not
guaranteed, for newly allocated memory to be all bits zero.
Please help me to understand this.

I have another couple of questions

1) how "memmove" works for overlapping objects ?
7.21.2.2:
The memmove function copies n characters from the object pointed to by s2 into the
object pointed to by s1. Copying takes place as if the n characters from the object
pointed to by s2 are ï¬rst copied into a temporary array of n characters that does not
overlap the objects pointed to by s1 and s2, and then the n characters from the
temporary array are copied into the object pointed to by s1.
2) Why the behavior of memcpy is undefined for overlapping objects?
The C99 rationale:
7.21.2 Copying functions
20
A block copy routine should be “rightâ€: it should work correctly even if the blocks being copied
overlap. Otherwise it is more difficult to correctly code such overlapping copy operations, and
portability suffers because the optimal C-coded algorithm on one machine may be horribly slow
on another.
25 A block copy routine should be “fastâ€: it should be implementable as a few inline instructions
which take maximum advantage of any block copy provisions of the hardware. Checking for
overlapping copies produces too much code for convenient inlining in many implementations.
The programmer knows in a great many cases that the two blocks cannot possibly overlap, so the
space and time overhead are for naught.
30 These arguments are contradictory but each is compelling. Therefore the Standard mandates two
block copy functions: memmove is required to work correctly even if the source and destination
overlap, while memcpy can assume non-overlapping operands and be optimized accordingly.
3) Is it possible to write strcpy function for overlapping object ?
If yes what would be the logic
Copy the source into a temporary buffer. Copy the temporary buffer
into the destination. Beware of buffer overflows.
 
S

somenath

Copy the source into a temporary buffer. Copy the temporary buffer
into the destination. Beware of buffer overflows.
I have tried to implement the strcpy for overlapping object as
mentioned bellow.
Is it ok ? please provide your thoughts.

char * safe_strcpy(char *src,char *dest)
{
size_t lengthOfsrc= strlen(src);
char *tempSrc= malloc(lengthOfsrc * sizeof(*tempSrc));
if (!tempSrc)
{
return NULL;
}
else
{/*enough memory available to copy source string to temp string*/
while(*tempSrc++ = *src++)
;
tempSrc = tempSrc -lengthOfsrc - 1 ;
while( *dest++ =*tempSrc++)
;
}
free(tempSrc);
tempSrc = NULL;
return dest;



}

Regards,
Somenath
 
R

Richard Heathfield

somenath said:
Hi All,
I am trying to understand the behavior of the memcpy and memmove.
While doing so I wrote a program as mentioned bellow .

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

#define SIZE_OF_DST 3
int main(void)
{
char src[]="somenath";
char *dest = malloc(SIZE_OF_DST * sizeof(*dest));
if(dest)
{
memcpy(dest,src,SIZE_OF_DST -1 );
src[SIZE_OF_DST]='\0';

I have read the other replies to this article, and several point out
that you meant dest, not src. But unless I've misread, none of them
have pointed out that it should be dest[SIZE_OF_DST - 1], not
dest[SIZE_OF_DST].

If you have N consecutive integer values and the first is 1, then the
last is N. Therefore, if the first is 0, the last is N - 1.
 
P

pete

somenath said:
Hi All,
I am trying to understand the behavior of the memcpy and memmove.
While doing so I wrote a program as mentioned bellow .

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

#define SIZE_OF_DST 3
int main(void)
{
char src[]="somenath";
char *dest = malloc(SIZE_OF_DST * sizeof(*dest));
if(dest)
{
memcpy(dest,src,SIZE_OF_DST -1 );
src[SIZE_OF_DST]='\0';
printf("\n Source = %s Destination = %s \n", src,dest);

}
else
{ /*Memory allocation failled */
printf("\n Not enough Memory \n");

}
return 0;
}

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

#define SIZE_OF_DST 3

int main(void)
{
char src[] = "somenath";
char dest[SIZE_OF_DST];

memcpy(dest, src, SIZE_OF_DST - 1);
dest[SIZE_OF_DST - 1] = '\0';
printf("\n Source = %s Destination = %s \n", src, dest);
return 0;
}
 
P

pete

somenath said:
I have tried to implement the strcpy for overlapping object as
mentioned bellow.
Is it ok ? please provide your thoughts.

char * safe_strcpy(char *src,char *dest)
{
size_t lengthOfsrc= strlen(src);
char *tempSrc= malloc(lengthOfsrc * sizeof(*tempSrc));

ptr = malloc(N * sizeof *ptr), just simply doesn't
cover every case of allocation.

This is the way to allocate memory for strings,
when you have a length value:

char *tempSrc= malloc(lengthOfsrc + 1);
 
A

Army1987

I have tried to implement the strcpy for overlapping object as
mentioned bellow.
Is it ok ? please provide your thoughts.

char * safe_strcpy(char *src,char *dest)
{
size_t lengthOfsrc= strlen(src);
char *tempSrc= malloc(lengthOfsrc * sizeof(*tempSrc));
if (!tempSrc)
{
return NULL;
}
else
{/*enough memory available to copy source string to temp string*/
while(*tempSrc++ = *src++)
;
This will copy the terminating null, too. You didn't allocate
space for it.
tempSrc = tempSrc -lengthOfsrc - 1 ;
while( *dest++ =*tempSrc++)
;
}
free(tempSrc);
tempSrc = NULL;
return dest;



}

Try
#define str_move(dest, src) memmove((dest), (src), strlen((src)) + 1)
 
A

Army1987

Try
#define str_move(dest, src) memmove((dest), (src), strlen((src)) + 1)

I hadn't seen what can happen if src has side effects. But the
point was showing the idea, which can be used unchanged to write a
function. (Or if you *really* want it, capitalize the name of the
macro so that it will be evident that it is a macro, and you'll be
careful not to pass arguments with side effects...)
 
P

pete

Army1987 said:
I hadn't seen what can happen if src has side effects. But the
point was showing the idea, which can be used unchanged to write a
function. (Or if you *really* want it, capitalize the name of the
macro so that it will be evident that it is a macro, and you'll be
careful not to pass arguments with side effects...)

I think it's best just to forget about str_move,
and write the memmove function call in line, in the source file.
Anybody reading the source code for comprehension
would have to look up str_move and wind up encountering
memmove anyway.

The subject line of this thread is:
Question regarding memcpy and memmove function

.... so, I think that suggesting using memmove directly
would be appropriate.

But I can't understand why using memmove
to implement an overlapping version of strcpy,
wouldn't occur immediately to someone
making a post with that subject line.
 
S

SM Ryan

# I think it's best just to forget about str_move,
# and write the memmove function call in line, in the source file.
# Anybody reading the source code for comprehension
# would have to look up str_move and wind up encountering
# memmove anyway.

With little effort you can expand that to a general
prohibition against typedefs and functions, because
in both cases you have to go look up the definitions.
(Of course it is possible to write language tools
that collect all the symbol definitions and references
into a machine readable format, and to have the edittor
able to read that and present you with the definition'
in a popup or such with a few keystrokes--but that is
terribly inefficent waste of machine resources.)
 
P

pete

SM said:
# I think it's best just to forget about str_move,
# and write the memmove function call in line, in the source file.
# Anybody reading the source code for comprehension
# would have to look up str_move and wind up encountering
# memmove anyway.

With little effort you can expand that to a general
prohibition against typedefs and functions, because
in both cases you have to go look up the definitions.

Concerning this macro:
#define str_move(dest, src) memmove((dest), (src), strlen((src)) + 1)

my opinion was that
memmove(dest, src, strlen(src) + 1)
wasn't any less cryptic than
str_move(dest, src)
and I didn't see any other purpose to this particular macro,
other than to attempt to make the code easier to read.
 
S

somenath

ptr = malloc(N * sizeof *ptr), just simply doesn't
cover every case of allocation.

This is the way to allocate memory for strings,
when you have a length value:

char *tempSrc= malloc(lengthOfsrc + 1);

I have changed my code as bellow . I was trying to test one
scenario . But i am not sure if the program is working
properly .Please provide some inputs

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

char * safe_strcpy(char *src,char *dest)
{
size_t lengthOfsrc= strlen(src);
char *tempSrc= malloc(lengthOfsrc + 1); /*this line is changed*/
if (!tempSrc)
{
return NULL;
}
else
{/*enough memory available to copy source string to temp string*/
while(*tempSrc++ = *src++)
;
tempSrc = tempSrc -lengthOfsrc - 1 ;
while( *dest++ =*tempSrc++)
;
}
free(tempSrc);
tempSrc = NULL;
return dest;



}
int main(void)
{
char msg[] = "hello, world!";
char *ptr = &msg[6];



char src[] = "somenath";

safe_strcpy(msg,ptr);
// strcpy(msg,ptr);
puts(msg);
return 0;
}

Output :
hello,hello, world!

is it correct ?

Regards,
Somenath
 
B

Barry Schwarz

Most of the standard copy functions have the destination as the first
argument.
I have changed my code as bellow . I was trying to test one
scenario . But i am not sure if the program is working
properly .Please provide some inputs

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

char * safe_strcpy(char *src,char *dest)
{
size_t lengthOfsrc= strlen(src);
char *tempSrc= malloc(lengthOfsrc + 1); /*this line is changed*/
if (!tempSrc)
{
return NULL;
}
else
{/*enough memory available to copy source string to temp string*/
while(*tempSrc++ = *src++)
;
tempSrc = tempSrc -lengthOfsrc - 1 ;
while( *dest++ =*tempSrc++)
;
}
free(tempSrc);
tempSrc = NULL;

Since tempSrc will cease to exist after the next statement, this
assignment is kind of a waste.
return dest;



}
int main(void)
{
char msg[] = "hello, world!";
char *ptr = &msg[6];



char src[] = "somenath";

It is good to be proud of your name but is it worth three blank lines
before and one after, especially since you don't use it. I suspect
you included this solely to suppress, not actually fix, an error
uncovered during testing.
safe_strcpy(msg,ptr);

Inside safe_strcpy:
src is set to &msg[0].
dest is set to &msg[6].
lengthofSrc is set to 13.
malloc succeeds and tempSrc holds the address of a 14 byte
block.
14 bytes are copied from msg++ to tempSrc++.
tempSrc is reset back to start of 14 byte block.
An attempt is made to copy 14 bytes from tempSrc++ to dest++.
As part of copying the eighth byte, dest is incremented beyond
the end of msg. This invokes undefined behavior as does all further
attempts to store into the byte dest points to.
// strcpy(msg,ptr);
puts(msg);
return 0;
}

Output :
hello,hello, world!

is it correct ?

safe_strcpy may be OK but main calls it in a manner that invokes
undefined behavior. msg needs to be an array of at least 20 bytes.


Remove del for email
 
P

pete

somenath wrote:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char * safe_strcpy(char *src,char *dest)
{
size_t lengthOfsrc= strlen(src);
char *tempSrc= malloc(lengthOfsrc + 1); /*this line is changed*/
if (!tempSrc)
{
return NULL;
}
else
{/*enough memory available to copy source string to temp string*/
while(*tempSrc++ = *src++)
;
tempSrc = tempSrc -lengthOfsrc - 1 ;
while( *dest++ =*tempSrc++)
;
}
free(tempSrc);

You're freeing (original tempSrc + lengthOfsrc + 1)
instead of (original tempSrc).
tempSrc = NULL;
return dest;

}
int main(void)
{
char msg[] = "hello, world!";

You don't have enough room in msg to do what you want.
char *ptr = &msg[6];

char src[] = "somenath";

Get rid of src.
safe_strcpy(msg,ptr);
// strcpy(msg,ptr);
puts(msg);
return 0;
}

/* BEGIN new.c */

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

char *safe_strcpy(char *src, char *dest);

int main(void)
{
char msg[] = "hello, world!\0hello, world!";
char *ptr = &msg[6];

if (safe_strcpy(msg, ptr) == NULL) {
puts("safe_strcpy(msg, ptr) == NULL");
}
puts(msg);
return 0;
}

char *safe_strcpy(char *src, char *dest)
{
char *const buff = malloc(strlen(src) + 1);
char *buff_ptr = buff;

if (buff == NULL) {
return NULL;
} else {
while ((*buff_ptr++ = *src++) != '\0') {
;
}
buff_ptr = buff;
while ((*dest++ = *buff_ptr++) != '\0') {
;
}
}
free(buff);
return dest;
}

/* END new.c */
 
S

somenath

somenath said:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char * safe_strcpy(char *src,char *dest)
{
size_t lengthOfsrc= strlen(src);
char *tempSrc= malloc(lengthOfsrc + 1); /*this line is changed*/
if (!tempSrc)
{
return NULL;
}
else
{/*enough memory available to copy source string to temp string*/
while(*tempSrc++ = *src++)
;
tempSrc = tempSrc -lengthOfsrc - 1 ;
while( *dest++ =*tempSrc++)
;
}
free(tempSrc);

You're freeing (original tempSrc + lengthOfsrc + 1)
instead of (original tempSrc).
tempSrc = NULL;
return dest;
}
int main(void)
{
char msg[] = "hello, world!";

You don't have enough room in msg to do what you want.
char *ptr = &msg[6];
char src[] = "somenath";

Get rid of src.


safe_strcpy(msg,ptr);
// strcpy(msg,ptr);
puts(msg);
return 0;
}

/* BEGIN new.c */

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

char *safe_strcpy(char *src, char *dest);

int main(void)
{
char msg[] = "hello, world!\0hello, world!";
char *ptr = &msg[6];

if (safe_strcpy(msg, ptr) == NULL) {
puts("safe_strcpy(msg, ptr) == NULL");
}
puts(msg);
return 0;

}

char *safe_strcpy(char *src, char *dest)
{
char *const buff = malloc(strlen(src) + 1);
char *buff_ptr = buff;

if (buff == NULL) {
return NULL;
} else {
while ((*buff_ptr++ = *src++) != '\0') {
;
}
buff_ptr = buff;
while ((*dest++ = *buff_ptr++) != '\0') {
;
}
}
free(buff);
return dest;

}

/* END new.c */

Many thanks for providing inputs.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,016
Latest member
TatianaCha

Latest Threads

Top