System::String question

I

Ioannis Vranos

I had reported this as a bug:



Description:

Default indexed property of System::String crashes for object with stack
semantics.

int main()
{
using namespace System;

String ms= "Test string";

char c;

for(long i=0; i<ms.Length; ++i)
c=ms;
}



Actual Results:

C:\c>cl /clr:safe temp.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 14.00.41013
for Microsoft (R) .NET Framework version 2.00.41013.0
Copyright (C) Microsoft Corporation. All rights reserved.

temp.cpp
Microsoft (R) Incremental Linker Version 8.00.41013
Copyright (C) Microsoft Corporation. All rights reserved.

/out:temp.exe
temp.obj

C:\c>temp

Unhandled Exception: System.NullReferenceException: Object reference not
set to
an instance of an object.
at main()

C:\c>



Expected Results:

C:\c>cl /clr:safe temp.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 14.00.41013
for Microsoft (R) .NET Framework version 2.00.41013.0
Copyright (C) Microsoft Corporation. All rights reserved.

temp.cpp
Microsoft (R) Incremental Linker Version 8.00.41013
Copyright (C) Microsoft Corporation. All rights reserved.

/out:temp.exe
temp.obj

C:\c>temp

C:\c>



And the response:

Edited by Microsoft on 2005-01-27 at 11:03:28

Thank you for submitting this to us. We will investigate and keep you
informed.
Visual C++ Team

Resolved as By Design by Microsoft on 2005-01-28 at 17:58:13

Looking at this, the bug is actually a problem with ill-formed code.
System::String without the caret for a handle is not allowed. The
language specification is being updated to reflect this.

Thanks for the feedback!
Brandon Bray



My question is: Wouldn't be System::String objects allowed with stack
semantics?
 
T

Tamas Demjen

That's odd. If I create my own ref class and instantiate it with the
stack syntax, it works. It's hard to understand why it wouldn't work
with strings. After all, the stack instantiation of ref classes is just
a syntactical trick, in the reality the object is not created on the
stack but on the managed heap. It just makes the programmer's job
easier, and the application safer. When we write

String ms= "Test string";
ms.[...]

I expect that the compiler generates this code (or at least functionally
equivalent):
String^ ms = gcnew String("Test string");
try
{
ms->[...]
}
finally
{
delete ms;
}

It sounds very odd to me that the stack syntax works with every ref
class, except String. I see no reason behind it. But I didn't bother
reading the entire standard proposal, so they should know better.

I've created a ScopedPtr ref class that's similar to boost::scoped_ptr.
It's a ref class that safeguards an unmanaged pointer, and so far it
worked with the stack syntax.

Tom
 
I

Ioannis Vranos

Tamas said:
That's odd. If I create my own ref class and instantiate it with the
stack syntax, it works. It's hard to understand why it wouldn't work
with strings. After all, the stack instantiation of ref classes is just
a syntactical trick, in the reality the object is not created on the
stack but on the managed heap. It just makes the programmer's job
easier, and the application safer. When we write

String ms= "Test string";
ms.[...]

I expect that the compiler generates this code (or at least functionally
equivalent):
String^ ms = gcnew String("Test string");
try
{
ms->[...]
}
finally
{
delete ms;
}

It sounds very odd to me that the stack syntax works with every ref
class, except String. I see no reason behind it. But I didn't bother
reading the entire standard proposal, so they should know better.

I've created a ScopedPtr ref class that's similar to boost::scoped_ptr.
It's a ref class that safeguards an unmanaged pointer, and so far it
worked with the stack syntax.


I just edited the bug report:


"Edited by Ioannis Vranos on 2005-01-31 at 17:42:13

Actually the reported bug was intended to be for stack semantics, and
since C++/CLI does not include implicit type conversions with
constructors, the code should have been:

int main()
{
using namespace System;

String ms("Test string");

char c;

for(long i=0; i<ms.Length; ++i)
c=ms;
}

I changed the posted code to this one, in the "Steps to Reproduce" below.

==> Still the crash remains the same."



My bug report was changed to

Status: Resolved
Resolution: By Design


after that obscure answer, and because of that I guess the bug will
remain...
 
K

Kapil Khosla [MSFT]

I know it looks odd, but you code would work in the following manner
int main()
{
using namespace System;

String ^ms("Test string"); // note the hat.

char c;

for(long i=0; i<ms->Length; ++i)
c=ms;
}

I will follow up up on why decided to disallow String with stack semantics
and allow ref class with stack semantics.
Thanks,
Kapil




Ioannis Vranos said:
Tamas said:
That's odd. If I create my own ref class and instantiate it with the
stack syntax, it works. It's hard to understand why it wouldn't work with
strings. After all, the stack instantiation of ref classes is just a
syntactical trick, in the reality the object is not created on the stack
but on the managed heap. It just makes the programmer's job easier, and
the application safer. When we write

String ms= "Test string";
ms.[...]

I expect that the compiler generates this code (or at least functionally
equivalent):
String^ ms = gcnew String("Test string");
try
{
ms->[...]
}
finally
{
delete ms;
}

It sounds very odd to me that the stack syntax works with every ref
class, except String. I see no reason behind it. But I didn't bother
reading the entire standard proposal, so they should know better.

I've created a ScopedPtr ref class that's similar to boost::scoped_ptr.
It's a ref class that safeguards an unmanaged pointer, and so far it
worked with the stack syntax.


I just edited the bug report:


"Edited by Ioannis Vranos on 2005-01-31 at 17:42:13
Actually the reported bug was intended to be for stack semantics, and
since C++/CLI does not include implicit type conversions with
constructors, the code should have been:

int main()
{
using namespace System;

String ms("Test string");

char c;

for(long i=0; i<ms.Length; ++i)
c=ms;
}

I changed the posted code to this one, in the "Steps to Reproduce" below.

==> Still the crash remains the same."



My bug report was changed to

Status: Resolved
Resolution: By Design


after that obscure answer, and because of that I guess the bug will
remain...
 
K

Kapil Khosla [MSFT]

To answer your question. System::String is immutable. It means that you
cannot modify the object once created. All methods exposed by the String
class actually create a new object containing the modification.

Thus, it doesnt make a lot of sense to have String object on the stack as we
cannot create a destructor for the String class. For all types where we
support the stack semantics, we require that the type must have a destructor
or the compiler should be able to create one.

Hope it helps,
Kapil

Kapil Khosla said:
I know it looks odd, but you code would work in the following manner
int main()
{
using namespace System;

String ^ms("Test string"); // note the hat.

char c;

for(long i=0; i<ms->Length; ++i)
c=ms;
}

I will follow up up on why decided to disallow String with stack semantics
and allow ref class with stack semantics.
Thanks,
Kapil




Ioannis Vranos said:
Tamas said:
That's odd. If I create my own ref class and instantiate it with the
stack syntax, it works. It's hard to understand why it wouldn't work
with strings. After all, the stack instantiation of ref classes is just
a syntactical trick, in the reality the object is not created on the
stack but on the managed heap. It just makes the programmer's job
easier, and the application safer. When we write

String ms= "Test string";
ms.[...]

I expect that the compiler generates this code (or at least functionally
equivalent):
String^ ms = gcnew String("Test string");
try
{
ms->[...]
}
finally
{
delete ms;
}

It sounds very odd to me that the stack syntax works with every ref
class, except String. I see no reason behind it. But I didn't bother
reading the entire standard proposal, so they should know better.

I've created a ScopedPtr ref class that's similar to boost::scoped_ptr.
It's a ref class that safeguards an unmanaged pointer, and so far it
worked with the stack syntax.


I just edited the bug report:


"Edited by Ioannis Vranos on 2005-01-31 at 17:42:13
Actually the reported bug was intended to be for stack semantics, and
since C++/CLI does not include implicit type conversions with
constructors, the code should have been:

int main()
{
using namespace System;

String ms("Test string");

char c;

for(long i=0; i<ms.Length; ++i)
c=ms;
}

I changed the posted code to this one, in the "Steps to Reproduce" below.

==> Still the crash remains the same."



My bug report was changed to

Status: Resolved
Resolution: By Design


after that obscure answer, and because of that I guess the bug will
remain...

 
T

Tamas Demjen

Thanks for the explanation, I didn't know that. I would still prefer a
compiler error or at least a warning, as opposed to just a runtime
exception. It's always good to catch such problems at compile time. Thanks,

Tom
 
I

Ioannis Vranos

Kapil said:
To answer your question. System::String is immutable. It means that you
cannot modify the object once created. All methods exposed by the String
class actually create a new object containing the modification.


Which return String ^.

Thus, it doesnt make a lot of sense to have String object on the stack as we
cannot create a destructor for the String class.


Why it does not. At the end of its scope, it can be considered unusable
(destroyed). I do not know its implementation details, it may not have
any resources to release apart from memory, but notationally I cannot
find any reason why it should not exist.

For all types where we
support the stack semantics, we require that the type must have a destructor
or the compiler should be able to create one.


Do you mean that the compiler can not produce a default String
destructor as is the case for all objects in C++? If yes, why?
 
K

Kapil Khosla [MSFTt]

Ioannis Vranos said:
Do you mean that the compiler can not produce a default String destructor
as is the case for all objects in C++? If yes, why?

That is correct. The reason is that System::String is an imported type from
the CLR. So, we cannot create a destructor for the imported type.

Thanks,
 

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

Top