Code:
union foo
{
char c;
int i;
};
void func(void * src)
{
union foo dest;
memcpy(&dest, src, sizeof(union foo)); //here
}
If I call func()
like this:
int main()
{
char c;
int i;
func(&c);
func(&i);
return 0;
}
In the call func(&c)
, the size of c
is less than sizeof(union foo)
, which may be dangerous, right?
Is the line with memcpy
correct? And if not, how to fix it?
What I want is a safe call to memcpy
that copy a void *
pointer to a union
.
A little background: this is extracted from a very complicated function, and the signature of func()
including the void *
parameter is out of my control. Of course the example does nothing useful, that's because I removed all the code that isn't relevant to provide an example with minimum code.
Yes it works. It behaves the same as looping character pointers over that number of bytes.
After declaration, we assign the address of 'a' variable to the pointer 'ptr'. Then, we assign the void pointer to the integer pointer, i.e., ptr1 without any typecasting because in C, we do not need to typecast while assigning the void pointer to any other type of pointer.
memcpy() function in C/C++ The function memcpy() is used to copy a memory block from one location to another. One is source and another is destination pointed by the pointer. This is declared in “string. h” header file in C language. It does not check overflow.
In the call
func(&c)
, the size ofc
is less thansizeof(union foo)
, which may be dangerous, right?
Right, this will lead to undefined behaviour. dest
will likely contain some bytes from memory areas surrounding c
, and which these are depends on the internal workings of the compiler. Of course, as long as you only access dest.c
, that shouldn't cause any problems in most cases.
But let me be more specific. According to the C standard, writing dest.c
but reading dest.i
will always yield undefined behaviour. But most compilers on most platforms will have some well-defined behaviour for those cases as well. So often writing dest.c
but reading dest.i
makes sense despite what the standard says. In this case, however, reading from dest.i
will still be affected by unknown surrounding variables, so it is undefined not only from the standards point of view, but also in a very practical sense.
There also is a rare scenario you should consider: c
might be located at the very end of allocated memory pages. (This refers to memory pages allocated from the operating system and eventually the memory management unit (MMU) hardware, not to the block-wise user space allocation done by malloc
and friends.) In this case, reading more than that single byte might cause access to unmapped memory, and hence cause a severe error, most likely a program crash. Given the location of your c
as an automatic variable in main, this seems unlikely, but I take it that this code snippet is only an example.
Is the line with
memcpy
correct? And if not, how to fix it?
Depends on what you want to do. As it stands, the code doesn't make too much sense, so I don't know what correct reasonable application you might have in mind. Perhaps you should pass the sizeof
the src
object to func
.
Is the line with memcpy correct? And if not, how to fix it?
you should pass the size of memory pointed by void pointer so you can know src
has this much size so you just need to copy this much of data...
Further more to be safe you should calculate the size of destination and based on that you should pass size so illegal access in reading and writing both can be avoided.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With