4

Can I reliably use memset and memcpy operators in C++ with memory been allocated with new?

Edited:

Yes, to allocate native data type

Example

BYTE *buffer = 0;
DWORD bufferSize = _fat.GetSectorSize();
buffer = new BYTE[bufferSize];

_fat.ReadSector(streamChain[0], buffer, bufferSize);

ULONG header = 0;
memcpy(&header, buffer, sizeof(ULONG));
Andres
  • 3,324
  • 6
  • 27
  • 32

5 Answers5

7

So long as you are only using new to allocate the built-in and/or POD types, then yes. However, with something like this:

std::string * s = new string;
memset( s, 0, sizeof(*s) );

then you would be looking at disaster.

I have to ask though, why you and others seem so enamoured with these functions - I don't believe I ever use them in my own code. Using std::vector, which has its own copy and assignment facilities seems like a better bet for memcpy(), and I've never really believed in the magic of setting everything to zero, which seems to be the main use for memset().

  • In my case, its because I came from pure C language, and it seems to be practical. But of course, I open for suggestions. – Andres Dec 30 '09 at 18:17
  • @Neil, how do you initialize an array of (say) integers to all-zeros? – Eli Bendersky Dec 30 '09 at 18:17
  • 1
    @Elii - Firstly, why would I want to? Secondly, std::vector v( 0,SIZE) –  Dec 30 '09 at 18:20
  • @Neil, I find it useful in C, mostly. One good and simple example is a hash table with chaining. Setting the bucket array to all-zeros at creation is required, and memset is good for that – Eli Bendersky Dec 30 '09 at 18:22
  • What if you are working with raw data, which is my case, reading data from some sort of IO (file, network etc) ? Is there an efficient way to do it without rely on byte buffers and mem...() functions? Sorry I know this should be a new question but we are already here :) – Andres Dec 30 '09 at 18:23
  • 2
    @Andres Like I said, use std::vector - it does everything that a manually allocated array does, and is much safer and more convenient. Yoy should also take a look at the STL alogorithms like std::copy. –  Dec 30 '09 at 18:25
  • As Neil said, usually, memset-like functionality isn't what you want in the first place. But *if* you do, then use `std::fill` instead. It is just as efficient, but works with non-POD types as well as POD. – jalf Dec 30 '09 at 18:57
  • If the only parts of the C++ STL you learn are `std::vector` and `std::map`, you'll *still* save yourself a mountain of work. It's really nice not to keep reinventing wheels. – Mike D. Dec 30 '09 at 19:01
  • It might be just me, but I often find that for resetting Windows API structs `memset` is really handy (well `memset` or `ZeroMemory`). It's all about the right tool for the task, and though there are newer and sometimes simpler alternatives, there can still be situations in which you may want to go back and use the old style functions, instead of any other. – Tommy Andersen Dec 30 '09 at 19:28
  • 2
    @TommyA: Plain value initialization will zero out POD structs. No need to call a separate function after the initialization. – jalf Dec 30 '09 at 19:45
  • According to this answer: https://stackoverflow.com/a/5914697/1423806 the memory zeroing in the default constructor has been introduced only recently in C++. Also be aware that using __memset__ on C++ objects is not only wrong but even more. It can lead to memory leaks and another bunch of nightmare. From the valgrind doc: _...some compilers add 3 words at the beginning of the std::string to store the length, the capacity and a reference count before the memory containing the array of characters._ – Bemipefe Apr 19 '23 at 11:02
2

Yes of course, though memory allocated with new is taken from the "free store" it is still just in the application memory address space. memset and memcpy simply take address parameters for a source and destination, and these parameters can technically be to any address in your application's address space.

In fact some of the standard library algorithms distill down to a simple memcpy themselves (vector source and target copies through iterators).

joshperry
  • 41,167
  • 16
  • 88
  • 103
2

Yes, you can, indeed

Here's a canonical implementation of memset (taken from the libc of Android):

void*  memset(void*  dst, int c, size_t n)
{
    char*  q   = dst;
    char*  end = q + n;

    for (;;) {
        if (q < end) break; *q++ = (char) c;
        if (q < end) break; *q++ = (char) c;
        if (q < end) break; *q++ = (char) c;
        if (q < end) break; *q++ = (char) c;
    }

  return dst;
}

It's obvious that the dst pointer could be allocated any valid way (new, malloc, or even statically) - memset doesn't care.

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
1

Depends what you have allocated. If you have allocated POD (Plain Old Data) i.e. done

char* p = new char[100];
then yes, it is no different from malloc. If you have allocated an object(s) then using memcpy or memset could lead to un-defined behavior.
tyranid
  • 13,028
  • 1
  • 32
  • 34
1

You mentioned using memset, but your code didn't call it.

You can leverage the features of the language to allocate & memset all in one blast:

int someInts [256] = {0};

This will allocate an array of 256 ints, and set each one to zero, accomplishing the same as:

int someInts[256];
memset(someInts, 0, sizeof(someInts));

...but possibly faster, depending on how your compiler will optimize the alloc-memset code block.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • It should also be noted, that the zero is unnecessary, `int someInts [256] = {};` would do just fine. – avakar Dec 30 '09 at 19:31
  • @avakar: True enough. My predilection is to include the zero in an attempt at writing self-documenting code. – John Dibling Dec 30 '09 at 19:32
  • Personally I find `{0}` confusing -- what's so special about the first element of the array that you specify its value explicitly? But your mileage may vary of course. – avakar Dec 30 '09 at 20:50
  • 1
    Well, I don't do this so that I understand my own code better -- I already understand what {} means. I actually do this so that programmers who are unfamiliar with this particular syntax at least get a clue what's happening here so that they can look it up in the text of their choice. Lots of otherwise skilled & experienced C++ programmers don't understand this syntax. I didn't even understand it (eg, knew it was allowed) until I read the Standard cover to cover, and how many C++ programmers do that? – John Dibling Dec 30 '09 at 21:22
  • 1
    For programmers who are unfamiliar with initializer semantics, it is better to confuse them with `{}` than to create an illusion of understanding with `{0}`. I've seen attempts to "n-initialize" an array with `{n}` more than once. – avakar Dec 30 '09 at 22:06