pointer and storage

D

dis_is_eagle

Hi.I have a question on the following statement.

char* a="hello";

The question is where "hello" gets stored.Is it in some static area
,stack or heap.I have observed that attempting to modify "hello"
results in segmentation fault.Thanks for any help.

Eric
 
D

deepak

Hi.I have a question on the following statement.

char* a="hello";

The question is where "hello" gets stored.Is it in some static area
,stack or heap.I have observed that attempting to modify "hello"
results in segmentation fault.Thanks for any help.

The *a will be stored in the readonly part of the data area.
Thats the reason behind the segmenatation fault.

-Deepak.
 
R

Richard Heathfield

(e-mail address removed) said:
Hi.I have a question on the following statement.

char* a="hello";

The question is where "hello" gets stored.Is it in some static area
,stack or heap.

It depends on the implementation. No implementation is required to use
stacks or heaps.

You would be well-advised to use const char * rather than mere char *.
I have observed that attempting to modify "hello"
results in segmentation fault.

The behaviour resulting from modifying a constant string is undefined. A
segmentation fault is one possible result. The absence of a segmentation
fault is another possible result. And the destruction of Rome by fire is
another possible result.
 
F

Frederick Gotham

(e-mail address removed) posted:
char* a="hello";


This is a definition of a non-const pointer to a non-const char. It also
initialises the pointer to the address of a string literal (which is il-
advised.)

The question is where "hello" gets stored.Is it in some static area
,stack or heap.I have observed that attempting to modify "hello"
results in segmentation fault.Thanks for any help.


The following two programs are equivalent:

/* Program 1 */

int main(void)
{
char const *p = "Hello"; return 0;
}

/* Program 2 */

char const str_literal1[] = {'H','e','l','l','o',0};

#define LITERAL1 (*(char(*)[sizeof str_literal1])&str_literal1)

int main(void)
{
char const *p = LITERAL1; return 0;
}
 
A

Ark

Richard said:
(e-mail address removed) said:


It depends on the implementation. No implementation is required to use
stacks or heaps.

You would be well-advised to use const char * rather than mere char *.


The behaviour resulting from modifying a constant string is undefined. A
segmentation fault is one possible result. The absence of a segmentation
fault is another possible result. And the destruction of Rome by fire is
another possible result.
I am confused profoundly.
I always thought that where the string literals are stored (RO vs. RW)
is implementation-defined (and decent compilers would allow me to choose
my way with a command-line switch).
However, the /type/ of (a pointer to) a string literal is char *,
regardless of the switch, or so I read the standard a while ago.
So the statement
*a='a';
must compile OK *without diagnostics* and then cause or not cause
undefined behavior depending on implementation-defined behavior.

<OT> BTW, as an embedded type, I talked myself out of using compound
literals because they end up in my scarce RAM. (IAR EWARM 4.40
toolchain.) I find it odd that IAR puts string literals, which are, at
least conceptually, compound literals, in RO and true (syntactically)
compound literals, in RW. </OT>

Can anyone shed a bright light on this?
Thank you,
- Ark
 
B

Ben Pfaff

Ark said:
I am confused profoundly.
I always thought that where the string literals are stored (RO vs. RW)
is implementation-defined (and decent compilers would allow me to choose
my way with a command-line switch).

The Standard doesn't say, so yes, the location of string literals
is defined by an implementation.
However, the /type/ of (a pointer to) a string literal is char *,
regardless of the switch, or so I read the standard a while ago.
So the statement
*a='a';
must compile OK *without diagnostics* and then cause or not cause
undefined behavior depending on implementation-defined behavior.

No compiler is required to compile anything without diagnostics.
The Standard does not restrict an implementation from diagnosing
anything at all. It does *require* a diagnostic for many
programs, but it does not *forbid* diagnostics for other
programs.

Furthermore, the statement in question yields undefined behavior,
so the program is not strictly conforming. Implementations are
only required to successfully translate and execution strictly
conforming programs. The Standard does not clearly distinguish
translation time and runtime, so one cannot even say that the
program should be successfully translated and then executed as
undefined behavior.
 
K

Keith Thompson

Ark said:
Richard Heathfield wrote: [...]
The behaviour resulting from modifying a constant string is
undefined. A segmentation fault is one possible result. The absence
of a segmentation fault is another possible result. And the
destruction of Rome by fire is another possible result.

It would be clearer to use the term "string literal" rather than
"constant string".
I am confused profoundly.
I always thought that where the string literals are stored (RO vs. RW)
is implementation-defined
Yes.

(and decent compilers would allow me to
choose my way with a command-line switch).

That's debatable. I don't see much advantage in allowing string
literals to be modifiable (except *maybe* to handle old and broken
code).
However, the /type/ of (a pointer to) a string literal is char *,
regardless of the switch, or so I read the standard a while ago.
Yes.

So the statement
*a='a';
must compile OK *without diagnostics* and then cause or not cause
undefined behavior depending on implementation-defined behavior.

The following:
char *a = "hello";
*a = 'a';
(assuming it appears in an appropriate context) is legal (it violates
no syntax rules or constraints), and a conforming compiler must accept
it. But, as always, a compiler is free to issue any diagnostics it
likes. The standard requires diagnostics in certain cases; it never
forbids them.

If the initialization is executed, it invokes undefined behavior. The
undefined behavior is unconditional, though the effects of the
undefined behavior can be literally anything. There is no
implementation-defined behavior involved (implementation-defined
behavior must be documented by the implementation, and there is no
documentation requirement here).
 
K

Keith Thompson

Ben Pfaff said:
The Standard doesn't say, so yes, the location of string literals
is defined by an implementation.

But it's not "implementation-defined" (i.e., the implementation isn't
required to document its choice).

[snip]
Furthermore, the statement in question yields undefined behavior,
so the program is not strictly conforming. Implementations are
only required to successfully translate and execution strictly
conforming programs. The Standard does not clearly distinguish
translation time and runtime, so one cannot even say that the
program should be successfully translated and then executed as
undefined behavior.

I don't think that's true. For example, this program:

#include <stdio.h>
#include <limits.h>
int main (void)
{
printf("INT_MAX = %d\n", INT_MAX);
return 0;
}

is not strictly conforming, since it produces output that depends on
implementation-defined behavior, but I don't believe an implementation
may reject it on that basis.

"Strictly conforming" programs are a very narrow class, and
"conforming" programs are a very wide class ("conforming" programs can
depend on any arbitrary compiler extensions). The standard doesn't
seem to have a name for the class of programs that must be accepted,
but whose behavior may depend on the implementation.
 
F

Frederick Gotham

Keith Thompson posted:
For example, this program:

#include <stdio.h>
#include <limits.h>
int main (void)
{
printf("INT_MAX = %d\n", INT_MAX);
return 0;
}

is not strictly conforming, since it produces output that depends on
implementation-defined behavior, but I don't believe an implementation
may reject it on that basis.


Are you saying that there's something wrong with that program? It seems
perfectly alright to me.
 
P

pete

deepak said:
The *a will be stored in the readonly part of the data area.

The rules of C, neither require nor prohibit
a string literal being stored in read only memory.
 
P

pete

Keith said:
Ben Pfaff said:
The Standard doesn't say, so yes, the location of string literals
is defined by an implementation.

But it's not "implementation-defined" (i.e., the implementation isn't
required to document its choice).

[snip]
Furthermore, the statement in question yields undefined behavior,
so the program is not strictly conforming. Implementations are
only required to successfully translate and execution strictly
conforming programs. The Standard does not clearly distinguish
translation time and runtime, so one cannot even say that the
program should be successfully translated and then executed as
undefined behavior.

I don't think that's true. For example, this program:

#include <stdio.h>
#include <limits.h>
int main (void)
{
printf("INT_MAX = %d\n", INT_MAX);
return 0;
}

is not strictly conforming, since it produces output that depends on
implementation-defined behavior, but I don't believe an implementation
may reject it on that basis.

"Strictly conforming" programs are a very narrow class, and
"conforming" programs are a very wide class ("conforming" programs can
depend on any arbitrary compiler extensions). The standard doesn't
seem to have a name for the class of programs that must be accepted,
but whose behavior may depend on the implementation.

"Correct program" comes pretty close.

N869
4. Conformance

[#3] A program that is correct in all other aspects,
operating on correct data, containing unspecified behavior
shall be a correct program and act in accordance with
5.1.2.3.
 
K

Keith Thompson

Frederick Gotham said:
Keith Thompson posted:

Are you saying that there's something wrong with that program? It seems
perfectly alright to me.

No, not at all. I was responding to what Ben Pfaff wrote (and you
snipped) upthread:

| Furthermore, the statement in question yields undefined behavior,
| so the program is not strictly conforming. Implementations are
| only required to successfully translate and execution strictly
| conforming programs.

The program is not strictly conforming, but it's still perfectly
valid.
 
B

Ben Pfaff

pete said:
"Correct program" comes pretty close.

That's a good name. I'll try to remember that.

When I wrote my earlier article in this thread, I knew that
"strictly conforming" was not a perfect term, but I didn't have a
better one and didn't feel like adding a lot of qualifiers or an
extended explanation.
 
K

Keith Thompson

Frederick Gotham said:
Keith Thompson posted:


Why isn't that program strictly conforming?

C99 4p5:

A _strictly conforming program_ shall use only those features of
the language and library specified in this International
Standard. It shall not produce output dependent on any
unspecified, undefined, or implementation-defined behavior, and
shall not exceed any minimum implementation limit.

The program's behavior is implementation-defined, since it depends on
the implementation-defined value of INT_MAX.

(You just downloaded n1124, so you could have looked up the definition
yourself.)
 
R

Richard Heathfield

Keith Thompson said:

Richard Heathfield wrote: [...]
The behaviour resulting from modifying a constant string is
undefined. A segmentation fault is one possible result. The absence
of a segmentation fault is another possible result. And the
destruction of Rome by fire is another possible result.

It would be clearer to use the term "string literal" rather than
"constant string".

Yes, I nearly said "string literal", and then I thought along these lines:
'The term "string literal" refers to a source level construct, whereas the
behaviour in question (the modification thereof) refers to something that
happens at runtime. If I say "string literal", someone will nit-pick it,
and say that the string literal only exists in the "mind" of the lexer, and
it can't ever be modified, because by the time modification is (putatively)
possible the string literal has done its bit as a compilation token, and no
longer exists. So I'll play safe and call it a constant string instead.'

So much for playing safe. :)

<snip>
 
C

Chris Torek

Keith Thompson said:
Yes, I nearly said "string literal", and then I thought along these lines:
'The term "string literal" refers to a source level construct, whereas the
behaviour in question (the modification thereof) refers to something that
happens at runtime. If I say "string literal", someone will nit-pick it ...

I think the most appropriate phrase would be: "an anonymous array
produced by a string literal". This is a little unweildy, I admit,
but it sidesteps the case in which a string literal is used to
initialize a named array:

char s[] = "some string literal";

C99 throws in an interesting wrinkle though, in that compound
literals can produce modifiable objects:

void f(void) {
int *p = (int []) { 1, 2, 3 };

p[1]++;
/* now the array has 1,3,3 in it */
...
}

This means one can write:

void g(void) {
char *s = (char []) { "some string" };
...
}

to obtain a write-able anonymous array. I think I can still get
away with the wording I used above, though, because this anonymous
array is actually produced by the compound literal, and merely
*initialized* (not in fact "produced") by the string literal.
 
O

Old Wolf

Frederick said:
The following two programs are equivalent:

/* Program 1 */

int main(void)
{
char const *p = "Hello"; return 0;
}

/* Program 2 */

char const str_literal1[] = {'H','e','l','l','o',0};

#define LITERAL1 (*(char(*)[sizeof str_literal1])&str_literal1)

int main(void)
{
char const *p = LITERAL1; return 0;
}

Well, both of those programs cause no observable behaviour
so they are both equivalent to:

int main(void)
{
return 0;
}
 
A

Ark

Keith said:
Ark said:
Richard Heathfield wrote: [...]
The behaviour resulting from modifying a constant string is
undefined. A segmentation fault is one possible result. The absence
of a segmentation fault is another possible result. And the
destruction of Rome by fire is another possible result.

It would be clearer to use the term "string literal" rather than
"constant string".
I am confused profoundly.
I always thought that where the string literals are stored (RO vs. RW)
is implementation-defined
Yes.

(and decent compilers would allow me to
choose my way with a command-line switch).

That's debatable. I don't see much advantage in allowing string
literals to be modifiable (except *maybe* to handle old and broken
code).
However, the /type/ of (a pointer to) a string literal is char *,
regardless of the switch, or so I read the standard a while ago.
Yes.

So the statement
*a='a';
must compile OK *without diagnostics* and then cause or not cause
undefined behavior depending on implementation-defined behavior.

The following:
char *a = "hello";
*a = 'a';
(assuming it appears in an appropriate context) is legal (it violates
no syntax rules or constraints), and a conforming compiler must accept
it. But, as always, a compiler is free to issue any diagnostics it
likes. The standard requires diagnostics in certain cases; it never
forbids them.

If the initialization is executed, it invokes undefined behavior. The
undefined behavior is unconditional, though the effects of the
undefined behavior can be literally anything. There is no
implementation-defined behavior involved (implementation-defined
behavior must be documented by the implementation, and there is no
documentation requirement here).
That's exactly where my comprehension fails me.
After
char *a = "hello";
the pointer /is/ initialized, and if, as Keith writes,
*a = 'a';
produces the UB unconditionally, it means that the initialization of the
pointer is unconditionally bad (for the type), isn't it? There must be a
reason (like "old broken code"? or something else?) why the type of
"hello" is not const char *.
OK, I can drill this case down my brain, but this leaves the following
question:
What are (all) legal initializations of char *a such that assigning to
*a is UB-free?
Thanks,
Ark
 
L

lovecreatesbea...

Keith said:
The following:
char *a = "hello";
*a = 'a';
If the initialization is executed, it invokes undefined behavior. The
undefined behavior is unconditional, though the effects of the
undefined behavior can be literally anything. There is no
implementation-defined behavior involved (implementation-defined
behavior must be documented by the implementation, and there is no
documentation requirement here).

Is it the initialization that causes the undefined behaviour, or will
it cause the UB? Do you mean the coming UB caused by the next
assignment statement above?
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top