A 'memset' question:

F

Frederick Gotham

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

Noah Roberts

Duane said:
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.
 
W

werasm

Frederick said:
(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
 
D

Daniel T.

Frederick Gotham said:
(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.)
 
F

Frederick Gotham

werasm posted:
...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".
 
W

werasm

Frederick said:
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
 
F

Frederick Gotham

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();
 
W

werasm

Frederick said:
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
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top