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

Weird pointer error

0 views
Skip to first unread message

Chris Mantoulidis

unread,
Feb 10, 2004, 8:31:25 AM2/10/04
to
I see some really weird output from this program (compiled with GCC
3.3.2 under Linux).

#include <iostream>
using namespace std;

int main() {
char *s;
s = "test1";
cout << "s = " << s << " and &s = " << &s << "\n";

char *s2;
s2 = "foo bar";
cout << "s2 = " << s2 << " and &s2 = " << &s2 << "\n";
cout << "so s = " << s << "\n";

int *i;
*i = 1;
cout << "i = " << *i << " and &i " << &i << "\n"; //could have used
i instead of &i

int j;
j = 4;
cout << "j = " << j << " and &j " << &j << "\n";

return 0;
}

---

BTW: I know I can initialize on definition.

Output of the program is:
s = test1 and &s = 0xbfffe354
s2 = foo bar and &s2 = 0xbfffe350
so s = test1
Segmentation fault (what else, lol)

--
I wrote this program because i wanted to see what happens when I
assign values to pointers when I don't initialize them. If I comment
out the s2 part, then the program works (no segfault).

Why would s2 make this problem?

Oh, as I said, if I remove the s2 part it works fine and j's address
is 4bytes before i (the pointer). So the compiler allocates memory
with decreasing order? Or is this platform dependent?

Thanks in advance,
cmad

Sharad Kala

unread,
Feb 10, 2004, 8:51:50 AM2/10/04
to

"Chris Mantoulidis" <cma...@yahoo.com> wrote in message
news:a8587dd9.04021...@posting.google.com...
So you agree now that pointers are evil :-) (I actually don't).

> If I comment
> out the s2 part, then the program works (no segfault).

It's not s2 that's the trouble in your program. It's i which is pointing to some
garbage address.
s and s2 are const string literals.

> Why would s2 make this problem?
>
> Oh, as I said, if I remove the s2 part it works fine and j's address
> is 4bytes before i (the pointer). So the compiler allocates memory
> with decreasing order? Or is this platform dependent?

hmm..well you should expect addresses on stack to be in decreasing
order..right?.

-Sharad


Rolf Magnus

unread,
Feb 10, 2004, 11:13:47 AM2/10/04
to
Chris Mantoulidis wrote:

> I see some really weird output from this program (compiled with GCC
> 3.3.2 under Linux).
>
> #include <iostream>
> using namespace std;
>
> int main() {
> char *s;
> s = "test1";

The above conversion shouldn't be used. "test1" is of type const
char[7], and you let a pointer to non-const char point to it. That's
dangerous, because it will seem as if you can change the literal, which
you actually can't.

> cout << "s = " << s << " and &s = " << &s << "\n";
>
> char *s2;
> s2 = "foo bar";
> cout << "s2 = " << s2 << " and &s2 = " << &s2 << "\n";
> cout << "so s = " << s << "\n";
>
> int *i;
> *i = 1;

*i is the integer which the pointer i points to. But the pointer isn't
initialized. It points just into the open sky. The behaviour of the
above assignment is undefined, because it is an attempt to write to
some random memory location that might not even belong to your program.

> cout << "i = " << *i << " and &i " << &i << "\n"; //could have used
> i instead of &i
>
> int j;
> j = 4;
> cout << "j = " << j << " and &j " << &j << "\n";
>
> return 0;
> }
>
> ---
>
> BTW: I know I can initialize on definition.
>
> Output of the program is:
> s = test1 and &s = 0xbfffe354
> s2 = foo bar and &s2 = 0xbfffe350
> so s = test1
> Segmentation fault (what else, lol)
>
> --
> I wrote this program because i wanted to see what happens when I
> assign values to pointers when I don't initialize them.

You don't assign to the pointer. You try to assign to what it points to.

> If I comment out the s2 part, then the program works (no segfault).
>
> Why would s2 make this problem?

You shouldn't care. The behaviour of your above program is undefined, so
according to the C++ standard, everything can happen. What you observe
above is just one instance of "undefined behaviour". Note that the
result can depend on anything. It might be different on different
compilers or on the same compiler on a different OS or hardware, or
even on the same system with different compiler settings or a newer
version of the same compiler. It isn't worth trying to find out why
something specific happens when you invoke undefined behaviour.

> Oh, as I said, if I remove the s2 part it works fine and j's address
> is 4bytes before i (the pointer). So the compiler allocates memory
> with decreasing order? Or is this platform dependent?

It is platform dependant.

David Harmon

unread,
Feb 10, 2004, 12:00:39 PM2/10/04
to
On Tue, 10 Feb 2004 19:21:50 +0530 in comp.lang.c++, "Sharad Kala"
<no.spam_s...@yahoo.com> was alleged to have written:

>> I wrote this program because i wanted to see what happens when I
>> assign values to pointers when I don't initialize them.
>So you agree now that pointers are evil :-) (I actually don't).

Uninitialized pointers are always evil.

Chris Mantoulidis

unread,
Feb 10, 2004, 2:55:09 PM2/10/04
to
> > If I comment
> > out the s2 part, then the program works (no segfault).
> It's not s2 that's the trouble in your program. It's i which is pointing to some
> garbage address.
> s and s2 are const string literals.

So the way of solving this is by using new (to s, s2 and/or i)? Okay
they're const string literals, so what? Why would s and/or s2 be
deleted before the end of main()?

> > Why would s2 make this problem?
> >
> > Oh, as I said, if I remove the s2 part it works fine and j's address
> > is 4bytes before i (the pointer). So the compiler allocates memory
> > with decreasing order? Or is this platform dependent?
> hmm..well you should expect addresses on stack to be in decreasing
> order..right?.

Why so? I could expect them to be in increasing order :/ In fact I did
expect them to be in increasing order ;) And since I'm a pointer n00b
and newbie, shouldn't you be talking about heap instead of stack? (for
pointers).

> -Sharad

Old Wolf

unread,
Feb 10, 2004, 6:05:58 PM2/10/04
to
> I see some really weird output from this program (compiled with GCC
> 3.3.2 under Linux).

> #include <iostream>
> using namespace std;
>
> int main() {

[snip code referring to "s2"]


> int *i;
> *i = 1;

[snip]
>
> return 0;


> }
>
> Output of the program is:

> Segmentation fault (what else, lol)
>

> I wrote this program because i wanted to see what happens when I
> assign values to pointers when I don't initialize them. If I comment
> out the s2 part, then the program works (no segfault).
>
> Why would s2 make this problem?

You caused UB with the "*i = 1" line. You should not be surprised
by any particular subsequent behaviour (including crashes,
failure to crash, and nasal demons).

The contents of your application's memory (which could determine
i's value before initialization) are affected by the other
allocations and function calls that you make.
You were (un) lucky in that without the s2 code, "i" happened to
point to memory that your platform thinks you are allowed to access,
and furthermore, memory that was not doing anything important,
so your antics did not cause the platform to complain.



> Oh, as I said, if I remove the s2 part it works fine and j's address
> is 4bytes before i (the pointer). So the compiler allocates memory
> with decreasing order? Or is this platform dependent?

Platform-dependent obviously. It could even give i and j the same address,
if they are never used concurrently, or they could not even have addresses
at all in some situations (eg. register variables)

Finally, you wrote:

> cout << "i = " << *i << " and &i " << &i << "\n";
>//could have used i instead of &i

You would get different results for "i" as for "&i"
(assuming you first fixed the UB).

Avinash

unread,
Feb 11, 2004, 1:26:39 AM2/11/04
to
#include <iostream>
using namespace std;

int main() {
char *s;
s = "test1";
cout << "s = " << s << " and &s = " << &s << "\n";

char *s2;
s2 = "foo bar";
cout << "s2 = " << s2 << " and &s2 = " << &s2 << "\n";
cout << "so s = " << s << "\n";

int *i;
int k = 1 ;
i = &k ;


cout << "i = " << *i << " and &i " << &i << "\n"; //could have used
i instead of &i

int j;
j = 4;
cout << "j = " << j << " and &j " << &j << "\n";

return 0;
}

cma...@yahoo.com (Chris Mantoulidis) wrote in message news:<a8587dd9.04021...@posting.google.com>...

Chris Mantoulidis

unread,
Feb 11, 2004, 10:21:13 AM2/11/04
to
> The above conversion shouldn't be used. "test1" is of type const
> char[7], and you let a pointer to non-const char point to it. That's
> dangerous, because it will seem as if you can change the literal, which
> you actually can't.

SO, to use a pointer I have to do one of the following:
1) If I want it to just point at an address (probably a variable's
address) then no need to allocate memory for it (with new).
2) If I want the pointer to have it's own value then I HAVE to use
new.

So with s, I must follow the 2nd rule, since I want s to have its own
value. Why would const char * work? I don't get it. Okay "test1" is of
type const char[], so what? Can't a pointer point at a const value? Or
is that a rule I've never seen? :( I don't get why const char *, would
work better than char *; and it does work better.

> *i is the integer which the pointer i points to. But the pointer isn't
> initialized. It points just into the open sky. The behaviour of the
> above assignment is undefined, because it is an attempt to write to
> some random memory location that might not even belong to your program.

Why doesn't the same happen for s or s2?

Karl Heinz Buchegger

unread,
Feb 11, 2004, 10:36:36 AM2/11/04
to
Chris Mantoulidis wrote:
>
> > The above conversion shouldn't be used. "test1" is of type const
> > char[7], and you let a pointer to non-const char point to it. That's
> > dangerous, because it will seem as if you can change the literal, which
> > you actually can't.
>
> SO, to use a pointer I have to do one of the following:
> 1) If I want it to just point at an address (probably a variable's
> address) then no need to allocate memory for it (with new).
> 2) If I want the pointer to have it's own value then I HAVE to use
> new.

no.
A pointer is a variable, just like an int variable is a variable.
A storage to store something there.

The difference is: an int variable holds some number, say 5 or 8 or 6712
while a pointer variable holds an address. Where this address comes from
is of little interest to the pointer variable, it makes no difference.

The prefix & operator is called the address-of operator. It's purpose
is to come up with the address of something.

So in
int i;
i is an int variable. This variable exists somewhere in memory and hence
has an address. This address can be stored in a pointer variable, since the
whole job of pointers variables is to store addresses.

int* Ptr;

Ptr = &i;

read the last line as: get the address of i and store it in Ptr.

Another possibility would be to use 'new'.
new's purpose is to allocate and reserve some storage somewhere in memory.
To inform you where in memory the reservation has taken place, it gives you
the address of that memory area. Again: There is an address and there is
the pointer variable.

Ptr = new int;

--------------------------------------------------------
What other operations besides storing an address can you do with pointers?
For one there is the dereference operator '*'. When written as a postfix
operator to a pointer, it means: fetch the address stored in that pointer
variable, because the actual operation will take place at whatever address
this will be.

*Ptr = 5;

read as: take the Ptr variable. In it you will find the address in memory
where the 5 should be stored.


Now in your specific case:

int* i;
*i = 2;

Where does i point to? What is the address stored in i? We don't know, the
address is completely unspecified. So assigning the 2 to the memory cell
with that unspecified address is a thing you must not do.


--
Karl Heinz Buchegger, GASCAD GmbH
Teichstrasse 2
A-4595 Waldneukirchen
Tel ++43/7258/7545-0 Fax ++43/7258/7545-99
email: kbuc...@gascad.at Web: www.gascad.com

Fuer sehr grosse Werte von 2 gilt: 2 + 2 = 5

Rolf Magnus

unread,
Feb 11, 2004, 11:32:56 AM2/11/04
to
Chris Mantoulidis wrote:

>> The above conversion shouldn't be used. "test1" is of type const
>> char[7], and you let a pointer to non-const char point to it. That's
>> dangerous, because it will seem as if you can change the literal,
>> which you actually can't.
>
> SO, to use a pointer I have to do one of the following:
> 1) If I want it to just point at an address (probably a variable's
> address) then no need to allocate memory for it (with new).
> 2) If I want the pointer to have it's own value then I HAVE to use
> new.

That's not "it's own value". A pointer is just a variable that stores an
address. It doesn't in itself have any other value than that address.
You can let a pointer point at anthing that has the right type. In the
above case 1, you'd just create a variable and let a pointer point to
it. That variable's life time is limited to the end of the block it was
defined in, so you can't do anything with its address afterwards. If
you want an object to live longer than that, you need to dynamically
allocate it, which is case 2.
Since the int you create with new is not a variable (variables always
have a name), you cannot access it directly. Therefore, 'new' returns
the address of the new object, and you can store that address in your
pointer. Still the object that it points to cannot be seen as the
pointer's "own value". What a pointer really points to doesn't matter
if you access an object through it, as long as that is an existing
object of the according type.

> So with s, I must follow the 2nd rule, since I want s to have its own
> value. Why would const char * work? I don't get it. Okay "test1" is of
> type const char[], so what? Can't a pointer point at a const value? Or
> is that a rule I've never seen? :( I don't get why const char *, would
> work better than char *; and it does work better.

There are four constness modifications for a pointer. The pointer itself
can be const or non-const (i.e. it can't/can be modified to point to
another address than it was initialized with), and the object that it
points to can be const or non-const (meaning you can't/can modify that
object through the pointer). So for a pointer to char, that is:

char* modifyable pointer to a modifyable char
const char* modifyable pointer to a constant char
char* const constant pointer to modifiable char
const char* const constant pointer to a constant char

Normally, if your object is already const, you can only let a pointer to
const point to it. So:

const char c('X');
char* p = &c;

won't work, because c is const, and you can't let a pointer to non-const
point to it, since that would relax the constness. Now string literals
are a special case. They are of type array of const char, and thus
cannot be modified. But there exists a special conversion rule that
makes it possible to still let a pointer to non-const char point to it.
The reason why that rule exists is historical, and mostly for
compatibility with C. You should however not make use of this, since it
can lead to errors that the compiler can't detect. E.g.:

char* hello = "Hello, world\n";


int main()
{
hello[1] = 'X';
}

The above code is illegal, because the string literal that 'hello'
points to must not be modified. But since you let a pointer to
non-const char point to it, the compiler won't detect that error.

>> *i is the integer which the pointer i points to. But the pointer
>> isn't initialized. It points just into the open sky. The behaviour of
>> the above assignment is undefined, because it is an attempt to write
>> to some random memory location that might not even belong to your
>> program.
>
> Why doesn't the same happen for s or s2?

Because both s and s2 are assigned the address of something before they
are used. You wrote:

  char *s;
  s = "test1";

This will let s point to the first character of the literal "test1".
Same for s2. But you don't do this for i. You create it uninitialized
and then try to assign to the integer that it points to without
actually letting it point to an integer before.

Chris Mantoulidis

unread,
Feb 12, 2004, 6:51:09 AM2/12/04
to
Thank you Karl and Rolf ;) That's a lot of explaining and now it's a
LOT more clear to me :) Thank you again

cmad

0 new messages