I was exploring memcpy in C++. I have a program that reads 10 bytes from a file called temp.txt. The content of the file is:
abcdefghijklmnopqrstuvwxyz
Here's the code:
// This file is called "temp.cpp"
#include <string>
#include <fcntl.h>
#include <iostream>
#include <unistd.h>
int main() {
int fd = open("temp.txt", O_RDONLY);
int buffer_size{10};
char buffer[11];
char copy_buffer[11];
std::size_t bytes_read = read(fd, buffer, buffer_size);
std::cout << "Buffer: " << buffer << std::endl;
printf("Buffer address: %p, Copy Buffer address: %p\n", &buffer, ©_buffer);
memcpy(©_buffer, &buffer, 7);
std::cout << "Copy Buffer: " << copy_buffer << std::endl;
return 0;
}
I read 10 bytes and store them (and \0 in buffer). I then want to copy the contents of buffer into copy_buffer. I was changing the number of bytes I want to copy in the memcpy() function. Here's the output:
memcpy(©_buffer, &buffer, 5); // abcde
memcpy(©_buffer, &buffer, 6); // abcdef
memcpy(©_buffer, &buffer, 7); // abcdefg
memcpy(©_buffer, &buffer, 8); // abcdefgh?C??abcdefghij
I noticed that the last output is weird. I tried printing the addresses of copy_buffer and buffer and here's what I got:
Buffer address: 0x16cf8f5dd, Copy Buffer address: 0x16cf8f5d0
Which means, when I copied 8 characters, copy_buffer did not terminate with a \0, so the cout went over to the next addresses until it found a \0. This explains the entire buffer getting printed since it has a \0 at its end.
Why doesn't the same happen when I memcpy() 5, 6, 7 bytes? Is it because there's a \0 at address 0x16cf8f5d7 which gets overwritten only when I copy 8 bytes?
\0inbuffer- no, you don't do that. Your program exhibits undefined behavior, and the question "why doesn't the same happen...?" is unanswerable, because everything can happen.std::coutfrom this snippet, it becomes pure C. So, you'd better tag C instead of C++. Otherwise,memcpyand raw arrays are not the goto in C++. C++20 preferred types forvoidbuffers arestd::array<std::byte, N>andstd::vector<std::byte>both of which can usedata(buffer)andsize(buffer)via ADL, or their member counterparts(buffer.size(),buffer.data()). For resource safety, I would wrapfdin some RAII class, before proceeding.