Reliably cross-platform determining read-only string

D

dascandy

Hi,

I was wondering, is it possible to determine whether a string can be
modified (const char *) by the application or whether it's located in
what's commonly .rodata?

Regards,
Peter
 
V

Victor Bazarov

I was wondering, is it possible to determine whether a string can be
modified (const char *) by the application or whether it's located in
what's commonly .rodata?

If it is possible, it would be implementation-defined. As for the
reliability of the method, you would have to talk to the compiler
manufacturers. There is no such thing as '.rodata' in standard C++.

V
 
D

dasjotre

Hi,

I was wondering, is it possible to determine whether a string can be
modified (const char *) by the application or whether it's located in
what's commonly .rodata?

Regards,
Peter

const char * declares a pointer to const character object.
it can not be modified. it is the same on all platforms and
all compilers. you can not determine, using C++,
whether an object is in static or dynamic storage.

for compile time type deduction you can use
type traits such as boost::is_const.

be careful thou.

boost::is_const<const char*>::value is false since the
pointer is not const, just the object it points to

boost::is_const<boost::remove_pointer<const char *>::type>::value
is true.

regards

DS
 
J

James Kanze

I was wondering, is it possible to determine whether a string can be
modified (const char *) by the application or whether it's located in
what's commonly .rodata?

If by "string", you mean "string literal", it can't be modified,
by definition. What happens if you try is undefined behavior,
which means you have no guarantees what so ever. (A compiler
could define this behavior, of course. Some Unix based
compilers actually do, for historical reasons---K&R C explicitly
allowed modification. But even then, there is generally an
option to disable this extension.)
 
J

JohnQ

I was wondering, is it possible to determine whether a string can be
modified (const char *) by the application or whether it's located in
what's commonly .rodata?

"If by "string", you mean "string literal", it can't be modified,
by definition. What happens if you try is undefined behavior,
which means you have no guarantees what so ever. (A compiler
could define this behavior, of course. Some Unix based
compilers actually do, for historical reasons---K&R C explicitly
allowed modification. But even then, there is generally an
option to disable this extension.)"

What was the reason for disallowing string literal modification?

John
 
D

dascandy

If by "string", you mean "string literal", it can't be modified,
by definition. What happens if you try is undefined behavior,
which means you have no guarantees what so ever. (A compiler
could define this behavior, of course. Some Unix based
compilers actually do, for historical reasons---K&R C explicitly
allowed modification. But even then, there is generally an
option to disable this extension.)

Can I determine at the receiving end whether the string passed is a
string literal or an allocated bit of memory?
 
J

James Kanze

What was the reason for disallowing string literal modification?

A more reasonable question would be: what was the reason for
allowing it in the first place? In the source code, a string
literal looks like a constant. Allowing modification means that
it isn't, e.g.:

char* p = "some text" ;

might actually set p to point to "something". Rather makes
reading source code a bit difficult.
 
J

James Kanze

Can I determine at the receiving end whether the string passed is a
string literal or an allocated bit of memory?

Overload on const. It won't identify the actual source, but it
will tell you whether you have a right to modify the string or
not. Consider:

void
f( const char* p )
{
std::cout << "const: " << p << std::endl ;
}

void
f( char* p )
{
std::cout << "non-const: " << p << std::endl ;
}

int
main()
{
f( "string literal" ) ;
char buf[] = "local array" ;
f( buf ) ;
char* dyn = new char[ sizeof( "dynamic
array" ) ] ;
strcpy( dyn, "dynamic array" ) ;
f( dyn ) ;
std::string str( "string " ) ;
f( str.c_str() ) ;
return 0 ;
}

Try it. String literals have type char const[], which converts
to char const*; local buffers or dynamically allocated memory
can have type char[], or char*. If overload resolution chooses
the char const* version, above, you can't modify the string; if
it chooses the char* version, and the calling code hasn't cast
away const somehow (including by assigning a string literal to a
char*), then you can.
 
D

dascandy

Overload on const. It won't identify the actual source, but it
will tell you whether you have a right to modify the string or
not. Consider:
Try it. String literals have type char const[], which converts
to char const*; local buffers or dynamically allocated memory
can have type char[], or char*. If overload resolution chooses
the char const* version, above, you can't modify the string; if
it chooses the char* version, and the calling code hasn't cast
away const somehow (including by assigning a string literal to a
char*), then you can.

The point was, do I have to copy the incoming string or can I use the
passed pointer as a permanently present entity. This was for an
embedded system with a bunch of const strings being used more or less
as identifiers. Not allocate&copying all of them would be a boon.
 
J

JohnQ

What was the reason for disallowing string literal modification?

"A more reasonable question would be: what was the reason for
allowing it in the first place? In the source code, a string
literal looks like a constant. Allowing modification means that
it isn't, e.g.:

char* p = "some text" ;

might actually set p to point to "something". Rather makes
reading source code a bit difficult."

I don't understand. But I have implemented something that relies upon the
modification of string literals. :( So you know I'm going to challenge the
reasoning behind disallowing it if it is not sound.

Kanze says: "Mikey, you can't have your cereal."
Mikey says: "But I'm hungry!"

(That was not the image I wished to create, but I thought it was cute enuff
to leave there). :)

John
 
J

James Kanze

I don't understand. But I have implemented something that relies upon the
modification of string literals. :( So you know I'm going to challenge the
reasoning behind disallowing it if it is not sound.

The reasoning is very sound: it results in absolutely unreadable
code, and is horrible software engineering. It's basically the
equivalent of self modifying code, where the actual code stops
corresponding to the source.
Kanze says: "Mikey, you can't have your cereal."
Mikey says: "But I'm hungry!"

More a question of:

Standard says: "Mikey, you can't have those yew berries."
Mikey says: "But I'm hungry!"
 
J

James Kanze

Overload on const. It won't identify the actual source, but it
will tell you whether you have a right to modify the string or
not. Consider:
Try it. String literals have type char const[], which converts
to char const*; local buffers or dynamically allocated memory
can have type char[], or char*. If overload resolution chooses
the char const* version, above, you can't modify the string; if
it chooses the char* version, and the calling code hasn't cast
away const somehow (including by assigning a string literal to a
char*), then you can.
The point was, do I have to copy the incoming string or can I use the
passed pointer as a permanently present entity. This was for an
embedded system with a bunch of const strings being used more or less
as identifiers. Not allocate&copying all of them would be a boon.

So overload the function.

Or... just pass the burden off to the user:). Specify that he
is responsible for assuring that the string passed in has
sufficient lifetime.
 
J

JohnQ

Can I determine at the receiving end whether the string passed is a
string literal or an allocated bit of memory?


"Try it. String literals have type char const[], which converts
to char const*; local buffers or dynamically allocated memory
can have type char[], or char*. If overload resolution chooses
the char const* version, above, you can't modify the string; if
it chooses the char* version, and the calling code hasn't cast
away const somehow (including by assigning a string literal to a
char*), then you can."

I think there should be a James Kanze day. Because if his mind doesn't
explode soon, mine surely will!

John ;)
 
J

JohnQ

I don't understand. But I have implemented something that relies upon the
modification of string literals. :( So you know I'm going to challenge the
reasoning behind disallowing it if it is not sound.

"The reasoning is very sound: it results in absolutely unreadable
code, and is horrible software engineering. It's basically the
equivalent of self modifying code, where the actual code stops
corresponding to the source."

Disallowing it is putting policy before mechanism. I think there is a place
for it though, just not in general/daily usage.
I can't see how you can liken it to self-modifying code since the literals
are data, not code.
Kanze says: "Mikey, you can't have your cereal."
Mikey says: "But I'm hungry!"

More a question of:

"Standard says: "Mikey, you can't have those yew berries."
Mikey says: "But I'm hungry!""

Eating fish (many/daily) from the oceans may very well cause cancer.
Occassionally eating some of those fish is probably OK. I have to go make a
tuna fish sandwich now... if I don't post again, then you were right.

John
 
D

dascandy

So overload the function.

Or... just pass the burden off to the user:). Specify that he
is responsible for assuring that the string passed in has
sufficient lifetime.

Overloading won't help (or I'd have to overload on const char[] and
hope the user doesn't figure out how to fake that) so I'd have to
leave it to soft documentation. I know that I can probably use a
linker variable plus a pointer comparison to determine whether it
needs copying but that's a trick I'd rather not do.

Regards and thanks,
Peter
 
B

Bo Persson

JohnQ wrote:
:: "The reasoning is very sound: it results in absolutely unreadable
:: code, and is horrible software engineering. It's basically the
:: equivalent of self modifying code, where the actual code stops
:: corresponding to the source."
::
:: Disallowing it is putting policy before mechanism. I think there
:: is a place for it though, just not in general/daily usage.
:: I can't see how you can liken it to self-modifying code since the
:: literals are data, not code.
::

Literals are constants, not variable data. That's why we invented
variables.

char* p = "some text"; // cannot be modified
char p[] = "some text"; // can be modified


What is the real problem? :)


Bo Persson
 
J

JohnQ

Bo Persson said:
JohnQ wrote:
:: "The reasoning is very sound: it results in absolutely unreadable
:: code, and is horrible software engineering. It's basically the
:: equivalent of self modifying code, where the actual code stops
:: corresponding to the source."
::
:: Disallowing it is putting policy before mechanism. I think there
:: is a place for it though, just not in general/daily usage.
:: I can't see how you can liken it to self-modifying code since the
:: literals are data, not code.
::

Literals are constants, not variable data. That's why we invented
variables.

char* p = "some text"; // cannot be modified
char p[] = "some text"; // can be modified


What is the real problem? :)

Maybe there isn't a problem. I was thinking that I couldn't do:

struct somestruct
{
char name[32];
};

static somestruct instance = {"My name"};

And then modify 'name'. Why I was thinking that, I have no idea.

John
 
D

dascandy

What is the real problem? :)

class xyz {
xyz(T *name) {
if (...) {
m_name = name;
} else {
m_name = new T(*name); // or similar
}
}
}

What's T and what do I place at the dots, so that this works?

I am fairly sure I can't put anything portable at the dots. "name <
_rodata_end" would work in some circumstances.
 

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,291
Messages
2,571,493
Members
48,164
Latest member
KerrieWind

Latest Threads

Top