I am trying to understand the scenarios in which call to memcpy can fail silently because invalid pointers will result in access violation/segfaults. Also, there will be issues in case of overlapping pointers. Apart from these, are there any other ways the memcpy call can fail? Or we can consider it'll pass all the time without any error. How to verify it?
-
1Just stick with `memmove()` – pmg Jan 22 '19 at 19:50
-
@FrançoisAndrieux I want to know in general what happens? – user1669844 Jan 22 '19 at 19:51
-
C. Failure might not cause an access violation, but corrupt the program's own data causing unexpected results to happen silently. One safety is to verify that the `size_t count` argument is no larger than the the destination size. But you can't consider it will pass all the time without any error. It is a brutal function which can (try to) destroy anything in its way. – Weather Vane Jan 22 '19 at 19:54
-
1Null pointers is another failure scenario, writing with pointers to constant (i.e. read only) data is another. – john Jan 22 '19 at 19:56
-
2Copying to read-only memory will cause trouble. – Jonathan Leffler Jan 22 '19 at 20:30
3 Answers
The memcpy
has the precondition that the memory areas will not overlap. You invoke undefined behavior if you violate that precondition.
Similarly, you also invoke undefined behavior if you read past the bounds of the source buffer or write past the bounds of the destination buffer. This is dictated in the standard.
When you invoke undefined behavior, you can't predict how the program will behave in the future (or even in the past). It could crash, it could output strange results, or it could appear to work normally.
Using a tool such as valgrind is very helpful in identifying when your program violates various memory constraints, such as reading or writing past the end of a buffer, using an uninitialized value, dereferencing a null pointer, or performing a double free.

- 205,898
- 23
- 218
- 273
If you give it valid pointers that do not overlap and you do not overrun the buffers with your reads/writes, it will not fail. If you do some of those things, it may still not fail, but could do unexpected things. It will always return dest.

- 635
- 3
- 13
I am trying to understand the scenarios in which call to memcpy can fail silently because invalid pointers will result in access violation/segfaults.
Typically when there's an access violation/segfault, software fails loudly. This can happen if memcpy()
is given dodgy pointers or a bad size, which includes "correct pointers but heap was corrupted" (e.g. the metadata that malloc()
/free()
uses to keep track of allocated areas was overwritten by a bug causing free()
to give the underlying virtual RAM back to the kernel for an area that should've been kept, and causing memcpy()
to fail with an access violation because an area it should've been able to access can't be accessed).
The other cases are external failure conditions. If the OS decided to send some of the data to swap space but gets a read error from the device when trying to fetch the data back from swap space when you try to access it, there's very little to OS can do about it (your process and any other process using that data can't continue correctly). If you're using ECC RAM and the memory controller says there's an uncorrectable error with the RAM you're using it's similar. It's also possible for the OS to use "lazy page allocation" (e.g. pages of memory are allocated when you write to them and not when you thought you allocated them) and "over commit" (pretend that more pages were allocated than can be provided), so that when memcpy()
writes to an area that was allocated the OS can't handle it (e.g. it triggers an "OOM/out of memory killer" that terminates a process to free up some RAM). Finally, it's possible for the code to be corrupted (e.g. faulty RAM without ECC, malicious attack like "Rowhammer", corrupted shared library, ...) so that (e.g.) using memcpy()
causes a SIGILL
. Of course all of these things aren't related to memcpy()
itself and can just as easily happen anywhere else.
Also, there will be issues in case of overlapping pointers.
Yes. Some (most) implementations of memcpy()
are optimised to copy larger blocks (e.g. optimised to use SSE on 80x86 and moving 16 bytes at a time) where if the areas overlap the data gets mangled. Some (most) implementations of memcpy()
assume that it can copy data in one specific direction which will cause data to be corrupted if areas overlap in the wrong way (e.g. if the implementation uses the "lowest address first" direction and the destination area overlaps and is at a higher address than the source, then writes to the destination will overwrite source data that hasn't been copied yet).
Apart from these, are there any other ways the memcpy call can fail?
No, I think I covered all the possible failure cases above.
Or we can consider it'll pass all the time without any error. How to verify it?
For the "overlapping areas" problem it shouldn't be hard to write a wrapper around memcpy()
that detects overlap and generates an error (so that it doesn't silently corrupt data). Unfortunately this only finds problems at run-time (after it's too late - e.g. possibly after it's been released and running on the end user's computer). For some of the cases might be easy enough to detect "overlapping areas" using a static source code analyser, but these cases are likely to be the "easily detected by testing at run-time before software is released" cases.
For some things (dodgy pointers, corrupted heap) there are tools (valgrind) to detect problems. Unfortunately these only detect problems when they actually happen (and don't detect problems that don't happen during testing but do happen when software is running on the end-user's computer).
For the remainder (OS failures and hardware failures), if you can't trust the OS or hardware then you can't assume any code that verifies anything will work properly either.

- 35,656
- 2
- 39
- 66