Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

memset missing from string.h or cstring

406 views
Skip to first unread message

Li Zhou

unread,
Nov 11, 2006, 10:33:52 PM11/11/06
to
Dear group,

I find that memset is not included in either string.h or cstring in
C++Builder. I think this is very serious bug which degrade C++Builder's
standard conformance.

Li Zhou

Ed Mulroy

unread,
Nov 12, 2006, 12:24:31 AM11/12/06
to
In both of C and C++ mode string.h includes _str.h which provides a function
prototype for memset.

. Ed

> Li Zhou wrote in message
> news:4556...@newsgroups.borland.com...

Li Zhou

unread,
Nov 12, 2006, 2:14:56 AM11/12/06
to

Can you verify that by compiling a program? _str.h is included by
string.h and cstring but my C++Builder ( Part of Borland Developer
Studio 2006 ) just can't find memset.

Li Zhou


John Grabner

unread,
Nov 12, 2006, 4:28:47 AM11/12/06
to
Li Zhou wrote:
> Can you verify that by compiling a program? _str.h is included by
> string.h and cstring but my C++Builder ( Part of Borland Developer
> Studio 2006 ) just can't find memset.
>
> Li Zhou
>
>
Show the code that does not compile.

John.

Li Zhou

unread,
Nov 12, 2006, 8:42:18 PM11/12/06
to
John Grabner wrote:

> Show the code that does not compile.
>
> John.

To duplicate this error, visit http://www.itk.org/files/v2.2/ and
download InsightToolkit-2.2.0 ( either the tar.gz or the zip ).
Uncompress the archive and use cmake ( download from
http://www.cmake.org ) to generate borland makefiles. The error will
appear while compiling metaEllipse.cxx

Li Zhou


Ed Mulroy

unread,
Nov 12, 2006, 9:38:31 PM11/12/06
to
That is not how things work. We do not download and uncompress a 20 meg
zipped file and a 3 meg zipped file, build an application with other
people's compilers, use it to create a tool which will create a make file
for our compiler then troubleshoot many megs of code to find where the
problems are.

For that you need to pay money for a consultant to do the significant hours
needed for that.

You are in a peer support group where fellow developers offer help on their
own time without asking for compensation.

Cut down the code you have to a minimum piece which compiles except for the
problem you have mentioned. Post that minimum piece of code. It typically
will be less than 50 lines.

Do not be suprised if you find that you have solved the problem in the
process of understanding the code enough to cut it down.

. Ed

> Li Zhou wrote in message

> news:4557...@newsgroups.borland.com...

Li Zhou

unread,
Nov 12, 2006, 11:40:44 PM11/12/06
to
Ed Mulroy wrote:
> That is not how things work. We do not download and uncompress a 20 meg
> zipped file and a 3 meg zipped file, build an application with other
> people's compilers, use it to create a tool which will create a make file
> for our compiler then troubleshoot many megs of code to find where the
> problems are.
>
> For that you need to pay money for a consultant to do the significant hours
> needed for that.
>
> You are in a peer support group where fellow developers offer help on their
> own time without asking for compensation.
>
> Cut down the code you have to a minimum piece which compiles except for the
> problem you have mentioned. Post that minimum piece of code. It typically
> will be less than 50 lines.
>
> Do not be suprised if you find that you have solved the problem in the
> process of understanding the code enough to cut it down.
>
> . Ed
>
>
>

Here is the code of metaEllipse.cxx. The memset call is in the Clear()
member function. The rest code is irrelevant.


#include <stdio.h>
#include <ctype.h>
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <metaUtils.h>
#include <metaObject.h>
#include <metaEllipse.h>

//
// MedImage Constructors
//
MetaEllipse::
MetaEllipse()
:MetaObject()
{
if(META_DEBUG) std::cout << "MetaEllipse()" << std::endl;
Clear();

}

//
MetaEllipse::
MetaEllipse(const char *_headerName)
:MetaObject()
{
if(META_DEBUG) std::cout << "MetaEllipse()" << std::endl;
Clear();
Read(_headerName);
}

//
MetaEllipse::
MetaEllipse(const MetaEllipse *_ellipse)
:MetaObject()
{
if(META_DEBUG) std::cout << "MetaEllipse()" << std::endl;
Clear();
CopyInfo(_ellipse);
}

MetaEllipse::
MetaEllipse(unsigned int dim)
:MetaObject(dim)
{
if(META_DEBUG) std::cout << "MetaEllipse()" << std::endl;
Clear();
}

//
MetaEllipse::
~MetaEllipse()
{
M_Destroy();
}

//
void MetaEllipse::
PrintInfo() const
{
MetaObject::PrintInfo();
std::cout << "Radius = ";
for(int i=0;i<m_NDims;i++)
{
std::cout << m_Radius[i] << " ";
}
std::cout << std::endl;
}

void MetaEllipse::
CopyInfo(const MetaEllipse * _ellipse)
{
MetaObject::CopyInfo(_ellipse);
}

void MetaEllipse::
Radius(const float* radius)
{
for(int i=0; i<m_NDims; i++)
{
m_Radius[i] = radius[i];
}
}


void MetaEllipse::
Radius(float radius)
{
for(int i=0;i<m_NDims;i++)
{
m_Radius[i] = radius;
}
}

void MetaEllipse::
Radius(float r1,float r2)
{
m_Radius[0] = r1;
m_Radius[1] = r2;
}

void MetaEllipse::
Radius(float r1,float r2, float r3)
{
m_Radius[0] = r1;
m_Radius[1] = r2;
m_Radius[2] = r3;
}

const float* MetaEllipse::
Radius(void) const
{
return m_Radius;
}

/** Clear ellipse information */
void MetaEllipse::
Clear(void)
{
if(META_DEBUG) std::cout << "MetaEllipse: Clear" << std::endl;
MetaObject::Clear();
memset(m_Radius, 0, 100*sizeof(float));

for(int i=0; i<m_NDims; i++)
{
m_Radius[i] = 1;
}
}

/** Destroy ellipse information */
void MetaEllipse::
M_Destroy(void)
{
MetaObject::M_Destroy();
}

/** Set Read fields */
void MetaEllipse::
M_SetupReadFields(void)
{
if(META_DEBUG) std::cout << "MetaEllipse: M_SetupReadFields" <<
std::endl;

MetaObject::M_SetupReadFields();

MET_FieldRecordType * mF;

int nDimsRecNum = MET_GetFieldRecordNumber("NDims", &m_Fields);

mF = new MET_FieldRecordType;
MET_InitReadField(mF, "Radius", MET_FLOAT_ARRAY, true,nDimsRecNum);
mF->terminateRead = true;
m_Fields.push_back(mF);

}

void MetaEllipse::
M_SetupWriteFields(void)
{
strcpy(m_ObjectTypeName,"Ellipse");
MetaObject::M_SetupWriteFields();

MET_FieldRecordType * mF;

mF = new MET_FieldRecordType;
MET_InitWriteField(mF, "Radius", MET_FLOAT_ARRAY, m_NDims,m_Radius);
m_Fields.push_back(mF);
}


bool MetaEllipse::
M_Read(void)
{
if(META_DEBUG) std::cout << "MetaEllipse: M_Read: Loading Header" <<
std::endl;

if(!MetaObject::M_Read())
{
std::cout << "MetaEllipse: M_Read: Error parsing file" << std::endl;
return false;
}

if(META_DEBUG) std::cout << "MetaEllipse: M_Read: Parsing Header" <<
std::endl;

MET_FieldRecordType * mF;

mF = MET_GetFieldRecord("Radius", &m_Fields);
if(mF->defined)
{
for(int i=0;i<m_NDims;i++)
{
m_Radius[i]= (float)mF->value[i];
}
}

return true;
}


Hans Zandbergen

unread,
Nov 13, 2006, 4:11:53 AM11/13/06
to

Hi,

1) You could have redused code to 3 lines.
2) memset is part of std
3) just add std:: before memset

Hans Zandbergen

Li Zhou

unread,
Nov 13, 2006, 5:07:39 AM11/13/06
to

The whole point is that C++ standard says memset is included from
string.h or cstring. Therefore accessing it under std nameplace is an error.

Alan Bellingham

unread,
Nov 13, 2006, 5:28:34 AM11/13/06
to
Li Zhou <zho...@aim.com> wrote:

>The whole point is that C++ standard says memset is included from
>string.h or cstring. Therefore accessing it under std nameplace is an error.

17.4.1.2/4

--------------------------------------------------------------------------
4 Except as noted in clauses 18 through 27, the contents of each header
cname shall be the same as that of the corresponding header name.h,
as specified in ISO/IEC 9899:1990 Programming Languages C (Clause 7),
or ISO/IEC:1990 Programming Languages佑 AMENDMENT 1: C Integrity,
(Clause 7), as appropriate, as if by inclusion. In the C++ Standard
Library, however, the declarations and definitions (except for names
which are defined as macros in C) are within namespace scope (3.3.5)
of the namespace std.
--------------------------------------------------------------------------

Note that last sentence - it's why Hans is correct, and you are not.

Alan Bellingham
--
ACCU Conference: 11-14 April 2007 - Paramount Oxford Hotel

Alan Bellingham

unread,
Nov 13, 2006, 5:17:39 AM11/13/06
to
Li Zhou <zho...@aim.com> wrote:

>#include <cstring>

> memset(m_Radius, 0, 100*sizeof(float));

To expand on what Hans said ...

Must be std::memset()

When including the xxx.h headers, the relevant declarations are all in
the global namespace. When including the cxxx headers, they are all
(except macros, of course) in std namespace.

This is as per the C++ Standard.

Note that some compilers - I'm looking at you, Visual C++ 5 - got this
wrong.

What happens when you include both xxx.h and cxxx versions of the same
header, I'm not sure. I suspect that the first inclusion is what
matters.

Chris Uzdavinis

unread,
Nov 13, 2006, 9:45:18 AM11/13/06
to
Li Zhou <zho...@aim.com> writes:

> #include <cstring>
...


> /** Clear ellipse information */
> void MetaEllipse::
> Clear(void)
> {

...
> memset(m_Radius, 0, 100*sizeof(float));
...
> }


Whenever you include a C++ header from the C standard library (with
'c' at the beginning of the name, and without the trailing .h) the
functions in that file are in the standard C++ namespace, std.
Therefore you must qualify your function calls with a std:: prefix.

--
Chris (TeamB);

Li Zhou

unread,
Nov 14, 2006, 7:51:14 PM11/14/06
to

Even if i include <string.h> instead of <cstring> memset could not be
found unless calling it under std nameplace. You can try it for
yourself. This is a real bug.

Chris Uzdavinis

unread,
Nov 14, 2006, 7:56:06 PM11/14/06
to
Li Zhou <zho...@aim.com> writes:

> Even if i include <string.h> instead of <cstring> memset could not be
> found unless calling it under std nameplace. You can try it for
> yourself. This is a real bug.

I cannot try it for myself, but I'll take your word on it.

Sounds strange, though.

--
Chris (TeamB);

Russell Hind

unread,
Nov 15, 2006, 3:59:02 AM11/15/06
to
Li Zhou wrote:
>
> Even if i include <string.h> instead of <cstring> memset could not be
> found unless calling it under std nameplace. You can try it for
> yourself. This is a real bug.
>

Ok, I've created a new console app in C++Builder 6, and used the
following code in the .cpp file:

#pragma hdrstop
#include <string.h>
int main(int argc, char* argv[])
{
char a[10];
memset(reinterpret_cast<void*>(a), '\0', 10);
return 0;
}

This compiles fine. no std:: required. As someone else mentioned if
you include <cstring> before <string.h> then this code will fail as
string.h will be ignored due to header guards.

Are you sure that <cstring> isn't being included somehow before string.h
in your case because as this example shows, if you just include
<string.h> then C++Builder *does* work correctly and puts memset in the
global namespace.

Have you tried this?

Cheers

Russell

Harold Howe [TeamB]

unread,
Nov 16, 2006, 4:07:26 PM11/16/06
to

> Ok, I've created a new console app in C++Builder 6, and used the
> following code in the .cpp file:
>
> #pragma hdrstop
> #include <string.h>
> int main(int argc, char* argv[])
> {
> char a[10];
> memset(reinterpret_cast<void*>(a), '\0', 10);
> return 0;
> }

Whoa, there's void* popping up again. Untyped pointers rule!

In reading this thread as a latecomer, I can't help but think there may
in fact be a real bug in here somewhere. A type of bug that is similar
to bugs that I remember from the past. Bugs involving the std namespace,
C library functions that are implemented as intrinsics, release builds,
and precompiled headers.

The cpp file that was posted looked like this:

#include <stdio.h>
#include <ctype.h>
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>

...

Li tried changing <cstring> to string.h, and *claims* that memset still
cannot be found. Now, throughout this thread, Li has been confused and
incorrect at various times, but his last post seems to indicate that he
now understands <cstring> vs <string.h>. So maybe there is a real bug.

The source file both includes <string> and string.h. Since there is no
#pragma hdrstop, the compiler is most likely trying to precompile these.
This is a slightly different than the code that you posted. Try
something along these lines instead:

#include <string>
#include <string.h>
#pragma hdrstop

int main(int argc, char* argv[])
{
char a[10];
memset(reinterpret_cast<void*>(a), '\0', 10);
return 0;
}

Compile both release and debug builds and see if you get an error (I
don't have BCB with me, but can try later).

I dug through my past bug reports to find code why this seems familiar.
The closest thing I could find was a bcb5 bug using this code:

#include <cstring>
#pragma hdrstop

#pragma argsused


int main(int argc, char* argv[])
{

char *s1 = "foo";
char *s2 = "bar";

std::strcmp(s1, s2);
return 0;
}

This used to generate a compiler error:
[C++ Error] Unit1.cpp(14): E2316 '__strcmp__' is not a member of 'std'

This is the opposite problem than the poster is having. This bug
involved precompiled headers and intrinsics, and only occurred in
release builds. It has since been fixed (I think).

H^2


Harold Howe [TeamB]

unread,
Nov 16, 2006, 6:53:45 PM11/16/06
to

> #include <string>
> #include <string.h>
> #pragma hdrstop
>
> int main(int argc, char* argv[])
> {
> char a[10];
> memset(reinterpret_cast<void*>(a), '\0', 10);
> return 0;
> }

Indeed, this is a bug in BCB 2006:

[C++ Error] Unit1.cpp(7): E2268 Call to undefined function 'memset'

The pragma is not needed. PCHs can be on or off, and it doesn't matter
whether you are doing a debug or a release build. Switching the order of
<string.h> and <string> makes the error go away.

This code compiles fine with MSVC 8.

H^2

Alex Bakaev [TeamB]

unread,
Nov 16, 2006, 8:44:19 PM11/16/06
to
Harold Howe [TeamB] wrote:
>
>> #include <string>
>> #include <string.h>
>> #pragma hdrstop
>>
>> int main(int argc, char* argv[])
>> {
>> char a[10];
>> memset(reinterpret_cast<void*>(a), '\0', 10);
>> return 0;
>> }
>
> Indeed, this is a bug in BCB 2006:
>

Doesn't the <string> bring memset into std namespace, so string.h
becomes irrelevant? Or should both std::memset and ::memset compile fine
with the given order of inclusion?


Comeau compiles this fine

//#include <string>
#include <string.h>


int main(int argc, char* argv[])
{
char a[10];
memset(reinterpret_cast<void*>(a), '\0', 10);

::memset(reinterpret_cast<void*>(a), '\0', 10);
return 0;
}

And this too:

#include <string>
//#include <string.h>


int main(int argc, char* argv[])
{
char a[10];
memset(reinterpret_cast<void*>(a), '\0', 10);

::memset(reinterpret_cast<void*>(a), '\0', 10);
return 0;
}

Harold Howe [TeamB]

unread,
Nov 16, 2006, 9:06:24 PM11/16/06
to

> Doesn't the <string> bring memset into std namespace, so string.h
> becomes irrelevant?

I don't know. In practice, including <string> seems to pull memset into
the global namespace in both VC 8 and gcc 3.4.4, but not in BCB.
However, the standard only mentions memset when discussing string.h and
cstring. Maybe BCB is correct here?

Both VC8 and gcc compile the example I posted where <string> is followed
by <string.h>. BCB seems wrong in this case, but I'm not as confident as
I was an hour ago.

H^2

Li Zhou

unread,
Nov 16, 2006, 9:48:45 PM11/16/06
to

So the problem is from <string>? Which should not be included to begin
with? So the proper thing to do is to report that <string> could not be
found, instead of accept it and disregard late appearance of <string.h>?


Chris Uzdavinis

unread,
Nov 16, 2006, 10:11:13 PM11/16/06
to
"Alex Bakaev [TeamB]" <zx...@att.net> writes:

> Doesn't the <string> bring memset into std namespace, so string.h
> becomes irrelevant? Or should both std::memset and ::memset compile
> fine with the given order of inclusion?

<string> and <string.h> contain entirely different things--the first
being the std::string class, and the second the typical C library
header. You are thinking of <cstring> for the header that memset into
std namespace.

--
Chris (TeamB);

Harold Howe [TeamB]

unread,
Nov 17, 2006, 10:45:33 AM11/17/06
to
Li Zhou wrote:

> So the problem is from <string>? Which should not be included to begin
> with? So the proper thing to do is to report that <string> could not be
> found, instead of accept it and disregard late appearance of <string.h>?

<string> is a valid header file, and is separate from <string.h>. I
don't know why the code you posted is including <string>, as it does not
seem to use anything provided by that header.

H^2

Old Wolf

unread,
Nov 19, 2006, 11:20:29 PM11/19/06
to

Russell Hind <no...@nowhere.com> wrote:
>Ok, I've created a new console app in C++Builder 6, and used
>the following code in the .cpp file:
>
>#pragma hdrstop
>#include <string.h>
>int main(int argc, char* argv[])
>{
> char a[10];
> memset(reinterpret_cast<void*>(a), '\0', 10);
> return 0;
>}

Argh! Why the pointless and ugly cast? Better:
memset(a, '\0', 10);

In fact, for purposes of testing the compiler, all you
need is:

int main()
{
memset;
}

Russell Hind

unread,
Nov 20, 2006, 4:06:29 AM11/20/06
to
Old Wolf wrote:
>
> Argh! Why the pointless and ugly cast? Better:
> memset(a, '\0', 10);
>

because it was test code and I didn't think it would work without the
cast and didn't bother to try. I'd really use something like this:

boost::array<char,10> a;
std::fill(a.begin(), a.end(), '\0');

If I were doing this correctly but that doesn't prove the problem.

Cheers

Russell

Chris Uzdavinis

unread,
Nov 20, 2006, 11:26:39 AM11/20/06
to
Russell Hind <no...@nowhere.com> writes:

How about

boost::array<char,10> a = {};

?
--
Chris (TeamB);

Russell Hind

unread,
Nov 21, 2006, 4:37:50 AM11/21/06
to
Chris Uzdavinis (TeamB) wrote:
>
> How about
>
> boost::array<char,10> a = {};
>

Probably but I'm never sure on initialisation syntax and/or Borland's
conformance to the standard in this way, especially if it was an array
of structs, so tend to avoid it.

Cheers

Russell

Chris Uzdavinis

unread,
Nov 21, 2006, 9:58:29 AM11/21/06
to
Russell Hind <no...@nowhere.com> writes:

One of the goals of the array class was to permit use as if it were a
real array, such as aggregate initialization (the curly braces), etc.

I don't know how well it works with Borland's compiler either, and
only assume it's ok.

--
Chris (TeamB);

0 new messages