By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,122 Members | 1,237 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,122 IT Pros & Developers. It's quick & easy.

A 'memset' question:

P: n/a
I met a question about memset and have no idea right now. Could anybody
give a clue? Thanks

memset is sometimes used to initialize data in a constructor like the
example below. What is the benefit of initializing this way? Does it
work in this example? Does it work in general ? Is it a good idea in
general?

class A {
public:
A();
private:
int a;
float f;
char str[35];
long *lp;
};

A::A()
{
memset(this, 0, sizeof(*this));
}

Jul 11 '06 #1
Share this Question
Share on Google+
27 Replies


P: n/a
In article <11**********************@m79g2000cwm.googlegroups .com>,
vo********@gmail.com wrote:
I met a question about memset and have no idea right now. Could anybody
give a clue? Thanks

memset is sometimes used to initialize data in a constructor like the
example below. What is the benefit of initializing this way? Does it
work in this example? Does it work in general ? Is it a good idea in
general?

class A {
public:
A();
private:
int a;
float f;
char str[35];
long *lp;
};

A::A()
{
memset(this, 0, sizeof(*this));
}
Those are good questions. Take a guess at the answers based on your
understanding on what memset does.

For example:

void foo( int* array, int length ) {
for ( int i = 0; i < length; ++i )
array[i] = 0;
}

void foo( int* array, int length ) {
memset( array, 0, length );
}

What is the benefit of using memset here? Does it work?
Jul 11 '06 #2

P: n/a

<vo********@gmail.comskrev i meddelandet
news:11**********************@m79g2000cwm.googlegr oups.com...
>I met a question about memset and have no idea right now. Could
anybody
give a clue? Thanks

memset is sometimes used to initialize data in a constructor like
the
example below. What is the benefit of initializing this way? Does
it
work in this example? Does it work in general ? Is it a good idea
in
general?
None, no, no, and no. :-)
>
class A {
public:
A();
private:
int a;
float f;
char str[35];
long *lp;
};

A::A()
{
memset(this, 0, sizeof(*this));
}
The memset function is used in C to initialize structs (or possibly
arrays), because C doesn't have constructors.

In C++ it is still allowed for C like objects (PODs), but not for
anything else. The fact that your class has a constructor rules out
the use of memset. The use of multiple access specifiers does too.

If you need initialization, use a constructor and trust the compiler
to optimize the code. If you just zero everything, the odds are high
that the compiler will do the equivalent of a memset anyway.

Bo Persson
Jul 11 '06 #3

P: n/a
volunte...@gmail.com wrote:
I met a question about memset and have no idea right now. Could anybody
give a clue? Thanks

memset is sometimes used to initialize data in a constructor like the
example below. What is the benefit of initializing this way? Does it
work in this example? Does it work in general ? Is it a good idea in
general?

class A {
public:
A();
private:
int a;
float f;
char str[35];
long *lp;
};

A::A()
{
memset(this, 0, sizeof(*this));
}
Using memset in C++ is generally discouraged. There's no problem
initializing POD structs and arrays (in fact, some memset
implementations are the most efficient way to do that), but when you
come to non-POD classes that could have virtual tables (or some other
virtual mechanism), it could spell disaster. See this FAQ:

http://www.parashift.com/c++-faq-lit....html#faq-20.4

That being said, your example probably works. It's just a dangerous
technique and so is best avoided. Prefer using initialization lists
(http://www.parashift.com/c++-faq-lit....html#faq-10.6) when
possible and other techniques when not. For instance, I would rewrite
your constructor like this:

A::A()
: a( 0 )
, f( 0 )
, lp( 0 )
{
str[0] = 0;
// Or if you want to inialize the whole array:
//std::fill( str, str + (sizeof(str)/sizeof(char)), 0 );
// or
//std::memset( str, 0, sizeof(str)/sizeof(char) );
}
Cheers! --M

Jul 11 '06 #4

P: n/a
In message <11*********************@75g2000cwc.googlegroups.c om>,
mlimber <ml*****@gmail.comwrites
>volunte...@gmail.com wrote:
>I met a question about memset and have no idea right now. Could anybody
give a clue? Thanks

memset is sometimes used to initialize data in a constructor like the
example below. What is the benefit of initializing this way? Does it
work in this example? Does it work in general ? Is it a good idea in
general?

class A {
public:
A();
private:
int a;
float f;
char str[35];
long *lp;
};

A::A()
{
memset(this, 0, sizeof(*this));
}

Using memset in C++ is generally discouraged. There's no problem
initializing POD structs and arrays (in fact, some memset
implementations are the most efficient way to do that), but when you
come to non-POD classes that could have virtual tables (or some other
virtual mechanism), it could spell disaster.
Also pointers and floating types. There's no guarantee for either that
all-bits-zero actually represents zero.
>See this FAQ:

http://www.parashift.com/c++-faq-lit....html#faq-20.4

That being said, your example probably works. It's just a dangerous
technique and so is best avoided. Prefer using initialization lists
(http://www.parashift.com/c++-faq-lit....html#faq-10.6) when
possible and other techniques when not. For instance, I would rewrite
your constructor like this:

A::A()
: a( 0 )
, f( 0 )
, lp( 0 )
{
str[0] = 0;
// Or if you want to inialize the whole array:
//std::fill( str, str + (sizeof(str)/sizeof(char)), 0 );
// or
//std::memset( str, 0, sizeof(str)/sizeof(char) );
}
Cheers! --M
--
Richard Herring
Jul 11 '06 #5

P: n/a
vo********@gmail.com wrote:
memset is sometimes used to initialize data in a constructor like the
example below. What is the benefit of initializing this way?
Job security.
Does it work in this example?
No.
Is it a good idea in general?
If you have no other way to hang on to your job, perhaps. But if there
is anyone
who does understand C++, it may in fact be bad for our job security.
class A {
public:
A();
private:
int a;
float f;
char str[35];
long *lp;
};

A::A()
{
memset(this, 0, sizeof(*this));
}
HTH,
Michiel Salters

Jul 11 '06 #6

P: n/a
memset is sometimes used to initialize data in a constructor like the
example below. What is the benefit of initializing this way?

None. There's more than one way to skin a cat, and this is a paricularly
poor method of skinning a cat.

Furthermore, it doesn't work on all cats, and thus cannot be accepted as
Standard-compliant portable code.

Does it work in this example?

If you're running Windows, then yes.

Does it work in general ?

No. For three reasons:

(1) Null pointers need not be "all bits zero" on every platform.
(2) The floating point value of 0.0 need not be "all bits zero" on every
platform.
(3) You can't use it on a class which has a non-trivial constructor.

Is it a good idea in general?

No, it's a very bad idea, and no decent programmer would do it.
Here's what you want:

class A {
public:

A() : a(),f(),str(),lp() {}

private:

int a;
float f;
char str[35];
long *lp;
};

--

Frederick Gotham
Jul 11 '06 #7

P: n/a
mlimber posted:
Using memset in C++ is generally discouraged.

No need to impose such a restriction.

There's no problem initializing POD structs and arrays

struct POD {

double a;
float b;
long double c;

char *p;
void *p2;
};
Don't memset that to all zero's unless your objective is to demonstrate
code which malfunctions on certain platforms because it invokes undefined
behaviour.

(in fact, some memset implementations are the most efficient way to do
that)


Not a chance. The most efficient way to default initialise an object is to
default initialise it:

int array[64] = {};
That being said, your example probably works.

Yes it probably does, but only because he's very likely to be running
Microsoft Windows.

It's just a dangerous
technique and so is best avoided.


If I see code like that, I presume that the person's a novice and has yet
to discover the right way of doing this (as opposed to the Microsoft way of
doing things).

A::A()
: a( 0 )
, f( 0 )
, lp( 0 )

Yes that's OK, but for consistency, I'd avocate the use of empty
parentheses.
--

Frederick Gotham
Jul 11 '06 #8

P: n/a

"Frederick Gotham" <fg*******@SPAM.comwrote in message
news:64*******************@news.indigo.ie...
> A::A()
: a( 0 )
, f( 0 )
, lp( 0 )


Yes that's OK, but for consistency, I'd avocate the use of empty
parentheses.
Why... to save a couple keystrokes? Why not be explicit? If you want the
value to be zero, then say so.

Personally, I'd probably do this:

A::A()
: a( 0 ),
f( 0.0f ),
lp( NULL )

That's pretty explicit as to what I'm doing, eh?

-Howrad

Jul 11 '06 #9

P: n/a
Frederick Gotham wrote:
mlimber posted:
Using memset in C++ is generally discouraged.

No need to impose such a restriction.
This thread demonstrates the many problems with using memset in C++.
Thus, I think "general discouragement" is appropriate.
There's no problem initializing POD structs and arrays


struct POD {

double a;
float b;
long double c;

char *p;
void *p2;
};
Don't memset that to all zero's unless your objective is to demonstrate
code which malfunctions on certain platforms because it invokes undefined
behaviour.
As Frederick and others pointed out, I was mistaken here. Pointers and
floating point values can still cause trouble on some platforms.
(in fact, some memset implementations are the most efficient way to do
that)

Not a chance. The most efficient way to default initialise an object is to
default initialise it:

int array[64] = {};
IIRC, some implementations replace calls to memset with
machine-specific instructions that initialize a chunk of memory at top
speed. Even so, any smart compiler should yield the same code when
default initializing, so there's really no reason to use memset.
A::A()
: a( 0 )
, f( 0 )
, lp( 0 )

Yes that's OK, but for consistency, I'd avocate the use of empty
parentheses.
A matter of preference. I initialized the missing member in the
constructor body, after all.

Cheers! --M

Jul 11 '06 #10

P: n/a
>That being said, your example probably works.
>

Yes it probably does, but only because he's very likely to be running
Microsoft Windows.
Why would you think that memsetting a non pod type
"works" on "Windows"?

We do cross platform development and I would
have a long discussion with any of our developers
that did this, even on Windows.

Jul 12 '06 #11

P: n/a
Duane Hebert posted:
>>That being said, your example probably works.


Yes it probably does, but only because he's very likely to be running
Microsoft Windows.

Why would you think that memsetting a non pod type
"works" on "Windows"?

Opps, I should have been explicit that I was referring to POD's only.

As far as I know, pointers and floating point types on Windows get "all bits
zero" as their default value.
--

Frederick Gotham
Jul 12 '06 #12

P: n/a

"Frederick Gotham" <fg*******@SPAM.comwrote in message
news:Fm*******************@news.indigo.ie...
>Why would you think that memsetting a non pod type
"works" on "Windows"?


Opps, I should have been explicit that I was referring to POD's only.
OK.
As far as I know, pointers and floating point types on Windows get "all
bits
zero" as their default value.
Not sure what you mean here by default value. Generally,
if you have a structure that you want initialized with default
values, you provide a ctor that does that.

Or are you talking about initializing a POD type with = {}? If so,
I don't know. What would be the values set on a *nix box?
I would provide a ctor with an ititializer list if I cared about
what the values were.
Jul 12 '06 #13

P: n/a
mlimber wrote:
Using memset in C++ is generally discouraged. There's no problem
initializing POD structs and arrays
Actually, memsetting even PODS is NOT guaranteed to be portable.
writing zeros bytes all over an object is NOT necessarily the
same as zero initializing it.
Jul 12 '06 #14

P: n/a
Ron Natalie wrote:
mlimber wrote:
Using memset in C++ is generally discouraged. There's no problem
initializing POD structs and arrays

Actually, memsetting even PODS is NOT guaranteed to be portable.
writing zeros bytes all over an object is NOT necessarily the
same as zero initializing it.
Correct. We've been over that already in this thread, however.

Cheers! --M

Jul 12 '06 #15

P: n/a

Frederick Gotham wrote:
mlimber posted:
Using memset in C++ is generally discouraged.


No need to impose such a restriction.
I've seen it (memset) to be the source of some hard to find errors. If
you consider the declaration...

void* memset( void* dest, int c, size_t count)

.... the fact that dest is void is concerning. One of the hard to find
errors were for example:

struct s
{
char nameArray[X][Y];
//...
};

s::s()
{
for( int i = 0; i < X; ++i )
{
memset (&nameArray[i], '\0', sizeof(nameArray[0]));
}
}

It compiles with a smile. Using something like std::fill does not cause
these "silent" errors. I would not trust anything that takes <void*as
argument :-), and if there were alternatives, I would go to great
lengths to use those.

Werner

Jul 12 '06 #16

P: n/a
werasm posted:

struct s
{
char nameArray[X][Y];
//...
};

s::s()
{
for( int i = 0; i < X; ++i )
{
memset (&nameArray[i], '\0', sizeof(nameArray[0]));
}
}

Did a four year old write that code? What exactly is its objective?

If you want to default initialise an array, then default initialise an
array:

struct s {

char array[4][5];

s() : array() {}
};

It compiles with a smile.

Which is why C++ is C++, and not C-sacrifice-efficiency-at-the-cost-of-
holding-the-hands-of-inapt-programmers.
--

Frederick Gotham
Jul 12 '06 #17

P: n/a

Frederick Gotham wrote:
werasm posted:

struct s
{
char nameArray[X][Y];
//...
};

s::s()
{
for( int i = 0; i < X; ++i )
{
memset (&nameArray[i], '\0', sizeof(nameArray[0]));
}
}


Did a four year old write that code? What exactly is its objective?
The point is that the compiler did not emit the diagnostic. memset is
dangerous, period.
>
If you want to default initialise an array, then default initialise an
array:

struct s {

char array[4][5];

s() : array() {}
};
Yes, compilers have default initialised arrays in a consistent way for
years :-). And all compilers conform :-). BTW, changing compilers and
architectures are not necessarily in the hands of the software
developer.

W

Jul 12 '06 #18

P: n/a
werasm posted:

The point is that the compiler did not emit the diagnostic. memset is
dangerous, period.

I think "memset" is quite simple. It takes three arguments:

(1) The address of a byte (in the form of a void* albeit).
(2) A byte value (e.g. 0xFF, or 0x23, or 0x1E).
(3) The quantity of bytes to set to the value in (2).
--

Frederick Gotham
Jul 12 '06 #19

P: n/a

Frederick Gotham wrote:
werasm posted:

The point is that the compiler did not emit the diagnostic. memset is
dangerous, period.


I think "memset" is quite simple. It takes three arguments:
Yes no doubt (very simple), but you're missing my point. In my original
example the four year old intended...

memset (nameArray[i], '\0', sizeof(nameArray[0]));

....but used...

memset (&nameArray[i], '\0', sizeof(nameArray[0]));

....instead. Huge difference, which was allowed by the compiler because
of (void*) being the first argument - no type safety. For this reason,
I don't like memset, no matter how easy it may be to type or use.

Specifying
>
(1) The address of a byte (in the form of a void* albeit).
(2) A byte value (e.g. 0xFF, or 0x23, or 0x1E).
(3) The quantity of bytes to set to the value in (2).
I (or the programmer who originally wrote that code) never doubted how
to use memset. The compiler he used simply did not support
default-initialization, and he was looking for an alternative (hence
memset). In this case he got confused by the fact that in a double
subscript array (as opposed to the single that he is used too),
specifying...

nameArray[i]

....already gave him the required address. He should not have used...

&nameArray[i]...

This mistake was unfortunately not detected by the naive (easy-to-use)
memset. That is why I will not use it, as all programmers forget to add
(or not add) a & here and there :-)

W
>

--

Frederick Gotham
Jul 12 '06 #20

P: n/a
werasm posted:
I (or the programmer who originally wrote that code) never doubted how
to use memset. The compiler he used simply did not support
default-initialization, and he was looking for an alternative (hence
memset).

Oh I understand.

(Of course though, if a compiler doesn't support default-initialisation, it
should be propelled with force in a radial motion off a tall cliff, in the
hope that it experiences maximal tensile stress as it impacts the ground.)
--

Frederick Gotham
Jul 12 '06 #21

P: n/a

Duane Hebert wrote:
That being said, your example probably works.

Yes it probably does, but only because he's very likely to be running
Microsoft Windows.

Why would you think that memsetting a non pod type
"works" on "Windows"?

We do cross platform development and I would
have a long discussion with any of our developers
that did this, even on Windows.
I've seen plenty of code riddle with memset this, even in non-pods.
When a class doesn't have virtual functions it often works...

I don't like it at all. I rarely use memset and usually only on arrays
of primitives.

Jul 12 '06 #22

P: n/a

Frederick Gotham wrote:
(Of course though, if a compiler doesn't support default-initialisation, it
should be propelled with force in a radial motion off a tall cliff, in the
hope that it experiences maximal tensile stress as it impacts the ground.)
....and what if that is the only compiler that supports that particular
OS? Boot the OS - HMMM, booting things are very easy if you program for
Windows or Linux. If you are programming for some foreign DSP, things
aren't that easy.

See your point, though - good you see mine which is

1. Why use type unsafe memset when typesafe std::fill can do the same
job (if std::fill is available, of course).
2. If you have to use memset due to circumstance, be sure to evaluate
each memset in the entire program. The same goes for memcpy, strcpy,
strncpy strset, sprintf and all those good 'oll C API functions :-).
Yes, they are all very easy to use, and equally easy to misuse.

Regards,

Werner

Jul 13 '06 #23

P: n/a
Frederick Gotham <fg*******@SPAM.comwrote:
(Of course though, if a compiler doesn't support default-initialisation, it
should be propelled with force in a radial motion off a tall cliff, in the
hope that it experiences maximal tensile stress as it impacts the ground.)
You'd probably feel the same about one of the compilers I use, if
someone tries to access a private member, it compiles (and emits a
warning.)
Jul 13 '06 #24

P: n/a
werasm posted:
Frederick Gotham wrote:
>(Of course though, if a compiler doesn't support
default-initialisation, it should be propelled with force in a radial
motion off a tall cliff, in the hope that it experiences maximal
tensile stress as it impacts the ground.)

...and what if that is the only compiler that supports that particular
OS? Boot the OS - HMMM, booting things are very easy if you program for
Windows or Linux. If you are programming for some foreign DSP, things
aren't that easy.

Hmm... OK.

If I were compelled to work with such a compiler, I would try to make the
best of a bad situation.
I'd start off with a template function (assuming the compiler supports
templates):

template<class T>
void DefInit(T &obj)
{
memset(&obj,0,sizeof obj);
}
And then everywhere I use this function, I would comment it like as follows:

int SomeFunc()
{
SomeStruct obj; DefInit(obj);

/* CAUTION

SomeStruct obj = {};
*/
}
So if it comes to a point where my compiler gets upgraded, I can simply
search through my source files for "CAUTION".
--

Frederick Gotham
Jul 13 '06 #25

P: n/a
Frederick Gotham wrote:
Hmm... OK.

If I were compelled to work with such a compiler, I would try to make the
best of a bad situation.
I'd start off with a template function (assuming the compiler supports
templates):
It does support templates and includes a version of the STL
>
template<class T>
void DefInit(T &obj)
{
memset(&obj,0,sizeof obj);
}
Yes, my solution was replacing the memset functions with the typesafe
std::fill or std::fill_n, whichever you prefer. As you said, many ways
to skin a cat, some better - some worse (like memset).

This is what I came up with:

struct s
{
char array[N];
//...
}

s::s()
{
std::fill( array, array+N, '\0' ); //or
std::fill_n( array, N, '\0' );
}

If I have to choose between std::fill and memset, std::fill wins every
time. The implementors could of course have done this:

namespace std{

template<class OutputIterator, class Size, class Type>
void fill_n(
OutputIterator first,
Size count,
const Type& val
);

//non-template on for char
void fill_n( char* first, size_t count, char val )
{
memset( first, val, count );
}

//and for other built in types
}//end std

This implies that you loose no efficiency for the char case. There are
of course better implementations making use of selecting a
implementation based on whether the type is builtin or not, but thats
beside the point (which is - drop memset, or isolate it). This you have
also done with your DefInit mechanism, therefore we are in agreement.

Kind regards,

Werner

Jul 13 '06 #26

P: n/a
werasm posted:
There are of course better implementations making use of selecting a
implementation based on whether the type is builtin or not, but thats
beside the point (which is - drop memset, or isolate it). This you have
also done with your DefInit mechanism, therefore we are in agreement.

Actually, I have just realised that there was no need for adding a
"CAUTION" comment to the code -- if the compiler were to be upgraded, we'd
only need to search for "DefInit".

Also, the template could be specialised to handle cases where the null
pointer value is not "all bits zero" and where the zero value for floating
type points is not "all bits zero". Something like the following for
instance:

template<std::size_t len>
void DefInit<double,len>(double (&array)[len])
{
double *p = array;

double const * const p_over = array + len;

do
{
*p++ = 0.;
} while(p != p_over);
}
You say that the compiler doesn't support default-initialisation. Are you
saying that the following doesn't work as it should?

SomeStruct obj = {};
How about if you replace it with the following; does it work then?
SomeStruct obj = SomeStruct();
--

Frederick Gotham
Jul 13 '06 #27

P: n/a

Frederick Gotham wrote:
werasm posted:
There are of course better implementations making use of selecting a
implementation based on whether the type is builtin or not, but thats
beside the point (which is - drop memset, or isolate it). This you have
also done with your DefInit mechanism, therefore we are in agreement.


Actually, I have just realised that there was no need for adding a
"CAUTION" comment to the code -- if the compiler were to be upgraded, we'd
only need to search for "DefInit".

Also, the template could be specialised to handle cases where the null
pointer value is not "all bits zero" and where the zero value for floating
type points is not "all bits zero". Something like the following for
instance:

template<std::size_t len>
void DefInit<double,len>(double (&array)[len])
{
double *p = array;

double const * const p_over = array + len;

do
{
*p++ = 0.;
} while(p != p_over);
}
You say that the compiler doesn't support default-initialisation. Are you
saying that the following doesn't work as it should?

SomeStruct obj = {};
Yes - on one of our older compilers it used to not work. The compiler
did support templates and we could use the STL. I'm not trying to find
the solution anymore. Our solution was to use std::fill - eventually.
We steer away from memset as far as possible.

Werner

Jul 14 '06 #28

This discussion thread is closed

Replies have been disabled for this discussion.