views:

493

answers:

5

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));
+4  A: 

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().

anon
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
@Neil, how do you initialize an array of (say) integers to all-zeros?
Eli Bendersky
@Elii - Firstly, why would I want to? Secondly, std::vector <int> v( 0,SIZE)
anon
@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
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
@Andres Like I said, use std::vector <char> - 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.
anon
thanks for the advice, I'll try to get used with then
Andres
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
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.
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.
TommyA
@TommyA: Plain value initialization will zero out POD structs. No need to call a separate function after the initialization.
jalf
+1  A: 

Yes of course, thought 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
A: 

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
Cool, but here the code assumes that the int will be 4 bytes always.
Andres
What? No - read it again.
Eli Bendersky
Ok, sorry :-)......
Andres
The 4 repetitions are called "loop unrolling". It increases efficiency for loops with very simple repeated statements
Eli Bendersky
Yes, I get it, thanks ;)
Andres
`memset` doesn't care, no, but the objects you're overwriting certainly does. It's not safe to do this on non-POD types.
jalf
Could you please explain your use of the word *canonical* in this context?
Rob Kennedy
@Rob: taken from a real C library implementation
Eli Bendersky
A: 

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
A: 

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
It should also be noted, that the zero is unnecessary, `int someInts [256] = {};` would do just fine.
avakar
@avakar: True enough. My predilection is to include the zero in an attempt at writing self-documenting code.
John Dibling
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
John Dibling
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