A 'memset' question:

V

volunteers

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));
}
 
D

Daniel T.

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 = 0;
}

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

What is the benefit of using memset here? Does it work?
 
B

Bo Persson

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
 
M

mlimber

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-lite/virtual-functions.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-lite/ctors.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
 
R

Richard Herring

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-lite/virtual-functions.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-lite/ctors.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
 
M

Michiel.Salters

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
 
F

Frederick Gotham

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;
};
 
F

Frederick Gotham

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.
 
H

Howard

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
 
M

mlimber

Frederick said:
mlimber posted:

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.
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.
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
 
D

Duane Hebert

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.
 
F

Frederick Gotham

Duane Hebert posted:
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.
 
D

Duane Hebert

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.
 
R

Ron Natalie

mlimber said:
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.
 
M

mlimber

Ron said:
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
 
W

werasm

Frederick said:
mlimber posted:



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, '\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
 
F

Frederick Gotham

werasm posted:

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

s::s()
{
for( int i = 0; i < X; ++i )
{
memset (&nameArray, '\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.
 
W

werasm

Frederick said:
werasm posted:

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

s::s()
{
for( int i = 0; i < X; ++i )
{
memset (&nameArray, '\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
 
F

Frederick Gotham

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

werasm

Frederick said:
werasm posted:




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, '\0', sizeof(nameArray[0]));

....but used...

memset (&nameArray, '\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

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

&nameArray...

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top