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

I'm going insane

3 views
Skip to first unread message

xvart

unread,
Jan 13, 2007, 3:19:41 AM1/13/07
to
WTF am I missing this just segfaults at the *pch=0; line, am I going
insane or what???

#include <iostream>
using namespace std;
#include <string.h>
int main()
{
char *sptr;
char *pch;
char *l="hello;world;this;is;a;test;";
cout<<"Starting"<<endl;
for(sptr=l,pch=l;(strchr(pch, ';')?pch = strchr(pch, ';'):pch =
strchr(pch, '\r')) > 0;sptr=++pch) {
*pch=0;
cout<<sptr<<endl;
}
cout<<"Ending"<<endl;
return 1;
}

Nikos Chantziaras

unread,
Jan 13, 2007, 4:06:27 AM1/13/07
to
xvart wrote:
> WTF am I missing

std::string

xvart

unread,
Jan 13, 2007, 4:13:15 AM1/13/07
to
Code is changed to the following and now works with "gcc version 4.1.1
20060525", the question is are the pages locked even when "l" is
defined as static and should then be on the heap. I thought static
meant on the heap, if so what is the difference between a static heap
allocation and one created with strdup or malloc? should I really ask
the gcc boys?

int main()
{
char *sptr;
char *pch;

char *l=strdup("hello;world;this;is;a;test;");
sptr=l;
pch=l;
while ( strchr(pch, ';')?(pch=strchr(pch, ';')):(pch=strchr(pch,
'\r')) ) {
*pch=0;
printf("%s\n",sptr);
sptr=++pch;
}
free(l);
return 1;
}

Pierre L.

unread,
Jan 13, 2007, 5:31:28 AM1/13/07
to
On Jan 13, 10:13 am, "xvart" <x...@languid.me.uk> wrote:
> Code is changed to the following and now works with "gcc version 4.1.1
> 20060525", the question is are the pages locked even when "l" is
> defined as static and should then be on the heap. I thought static
> meant on the heap, if so what is the difference between a static heap
> allocation and one created with strdup or malloc?

You might want to read comp.lang.c faq 1.32
Or as Nikos pointed it out, use std::string if you're into C++.

> should I really ask the gcc boys?

Probably not.

--
Pierre

Paul F. Johnson

unread,
Jan 13, 2007, 7:07:35 AM1/13/07
to
Hi,

xvart wrote:

> char *l=strdup("hello;world;this;is;a;test;");

> free(l);

You've not allocated a memory block to l, so using free is going to cause
undefined behaviour.

TTFN

Paul
--
Sie können mich aufreizen und wirklich heiß machen!

Måns Rullgård

unread,
Jan 13, 2007, 7:18:59 AM1/13/07
to
"Paul F. Johnson" <pa...@all-the-johnsons.co.uk> writes:

> Hi,
>
> xvart wrote:
>
>> char *l=strdup("hello;world;this;is;a;test;");
>> free(l);
>
> You've not allocated a memory block to l, so using free is going to cause
> undefined behaviour.

strdup() allocates memory with malloc(), so free() is perfectly in
order there.

--
Måns Rullgård
m...@inprovide.com

Måns Rullgård

unread,
Jan 13, 2007, 7:32:03 AM1/13/07
to
"xvart" <xv...@languid.me.uk> writes:

String constants are stored in the read-only data section, as
modifying them rarely is what you want.

--
Måns Rullgård
m...@inprovide.com

Jens Thoms Toerring

unread,
Jan 13, 2007, 7:51:26 AM1/13/07
to
xvart <xv...@languid.me.uk> wrote:
> Code is changed to the following and now works with "gcc version 4.1.1
> 20060525", the question is are the pages locked even when "l" is
> defined as static and should then be on the heap. I thought static
> meant on the heap, if so what is the difference between a static heap
> allocation and one created with strdup or malloc? should I really ask
> the gcc boys?

A line like

char *l = "hello;world;this;is;a;test;";

creates a pointer, pointing to a so-called "string literal".
And string literals can't be changed, neither in C or C++.
It doesn't matter where the compiler puts them, all you
need to know is that trying to modify a string literal is
forbidden - it can be in write protected memory. Putting
a 'static' in front of the pointer won't change anything
about it, that only changes some properties of the pointer
variable, not what it's pointing to. What you could put in
front of it instead is 'const', that would enable the com-
piler to complain if you try to change what 'l' is pointing
to. BTW, some implementations don't enforce that literal
strings can't be changed, so people get away with it and
start believing that it would be ok. But they are in for
a bad surprise if they ever try to compile their programs
with a different compiler or on a different system...

On the other hand, with

char *l = sstrdup( "hello;world;this;is;a;test;" );

you get a pointer to a copy of the literal string, where
the copy is now in memory you own (it has freshly been
allocated for you) and you can change that to your hearts
desires, that's why your new version works.

> defined as static and should then be on the heap. I thought static
> meant on the heap, if so what is the difference between a static heap
> allocation and one created with strdup or malloc? should I really ask

You're looking at this the wrong way round. There are
certain rules the language imposes and putting some-
thing on the heap or somewhere else may be a way to
implement these rules the compiler writers chose. But
by using such arguments you are trying to deduce the
rules of the language from the way you imagine it's
implemented in a certain case, and that probably won't
get you very far (even if your assumption should be
correct).
Regards, Jens
--
\ Jens Thoms Toerring ___ j...@toerring.de
\__________________________ http://toerring.de

Stephane CHAZELAS

unread,
Jan 13, 2007, 8:27:09 AM1/13/07
to
2007-01-13, 12:51(+00), Jens Thoms Toerring:

> xvart <xv...@languid.me.uk> wrote:
>> Code is changed to the following and now works with "gcc version 4.1.1
>> 20060525", the question is are the pages locked even when "l" is
>> defined as static and should then be on the heap. I thought static
>> meant on the heap, if so what is the difference between a static heap
>> allocation and one created with strdup or malloc? should I really ask
>> the gcc boys?
>
> A line like
>
> char *l = "hello;world;this;is;a;test;";
>
> creates a pointer, pointing to a so-called "string literal".
> And string literals can't be changed, neither in C or C++.
[...]

Could also be opposed to:

char l[] = "hello;world;this;is;a;test;";

That creates an array of chars initialiased in that case to an
array of 28 elements, same as:

char l[] = { 'h', 'e', ... ';', '\0' };

and in which case is read-write.

And you can do:

char k[] = "hello;world;this;is;a;test;";
char *l = k;


--
Stéphane

Paul F. Johnson

unread,
Jan 13, 2007, 9:16:26 AM1/13/07
to
Hi

Måns Rullgård wrote:

>> You've not allocated a memory block to l, so using free is going to cause
>> undefined behaviour.
>
> strdup() allocates memory with malloc(), so free() is perfectly in
> order there.

Um...

strdup returns a pointer to a new string which is a duplicate of the string
passed in. Memory for the string is obtained using malloc.

Nowhere in the code is there a malloc - unless I've misunderstood something,
it's up to the user to do something like

char *m = malloc(300) (say)
m = strdup(foo)

otherwise all that gets returned into m (without the malloc) is going to be
gibberish.

Stephane CHAZELAS

unread,
Jan 13, 2007, 9:28:22 AM1/13/07
to
2007-01-13, 14:16(+00), Paul F. Johnson:

> Hi
>
> Måns Rullgård wrote:
>
>>> You've not allocated a memory block to l, so using free is going to cause
>>> undefined behaviour.
>>
>> strdup() allocates memory with malloc(), so free() is perfectly in
>> order there.
>
> Um...
>
> strdup returns a pointer to a new string which is a duplicate of the string
> passed in. Memory for the string is obtained using malloc.
>
> Nowhere in the code is there a malloc - unless I've misunderstood something,
> it's up to the user to do something like
>
> char *m = malloc(300) (say)
> m = strdup(foo)

???

There, malloc allocated 300 bytes and returns a pointer to
that which is stored into the m variable. Then you override the
value of m with the pointer returned by strdup. So the original
value returned by malloc is now lost, so you'll have no way to
free it.

> otherwise all that gets returned into m (without the malloc) is going to be
> gibberish.

[...]

No, strdup does allocate enough space to hold a copy of the
input string, copies the input string there an returns a pointer
to the new allocated space.

You can then use free(3) on the value returned by strdup.

--
Stéphane

xvart

unread,
Jan 13, 2007, 11:26:59 AM1/13/07
to
Thanks all, found the part of the spec sec 6.1.4 that covers string
literals.. yep means string const.

matevzb

unread,
Jan 13, 2007, 12:33:00 PM1/13/07
to
On Jan 13, 1:51 pm, j...@toerring.de (Jens Thoms Toerring) wrote:
> char *l = "hello;world;this;is;a;test;";
>
> creates a pointer, pointing to a so-called "string literal".
> And string literals can't be changed, neither in C or C++.
> It doesn't matter where the compiler puts them, all you
> need to know is that trying to modify a string literal is
> forbidden - it can be in write protected memory.
No, it isn't forbidden. In C this falls under "undefined behaviour", so
a compiler could put string literals in read-only or in read-write
memory. Usually there's a compiler option to control this, like
-fwritable-strings for gcc.
--
WYCIWYG

matevzb

unread,
Jan 13, 2007, 12:36:39 PM1/13/07
to
Eh, I just saw this is C++. If I'm not mistaken, it's the same there
according to ISO C++:
"The effect of attempting to modify a string literal is undefined."
--
WYCIWYG - what you C is what you get

Giorgos Keramidas

unread,
Jan 13, 2007, 12:39:56 PM1/13/07
to
On 13 Jan 2007 00:19:41 -0800, "xvart" <xv...@languid.me.uk> wrote:
> WTF am I missing this just segfaults at the *pch=0; line, am I going
> insane or what???

Source code re-indented for clarity.

% #include <iostream>
%
% using namespace std;
%
% #include <string.h>
%
% int main()
% {
% char *sptr;
% char *pch;
% char *l = "hello;world;this;is;a;test;";

The type of ""hello;world;this;is;a;test;" is not (char *), but (const
char *). This means that the compiler is free to choose to store it
inside a memory region that is mapped as read-only by the time your
main() function runs.

% cout << "Starting" << endl;
%
% for (sptr = l, pch = l;
% (strchr(pch, ';') ?
% pch = strchr(pch, ';') :
% pch = strchr(pch, '\r')) > 0;
% sptr = ++pch)
% {
% *pch = 0;

... and that's why this will fail. You are trying to write, through a
(char *) pointer to a (const char *) region.

% cout << sptr << endl;
% }
% cout << "Ending" << endl;
% return 1;
% }

The fix is simple. Change the type of 'l' from (char *) to:

char l[] = "hello;world;this;is;a;test;";

Then the compiler will create a *mutable* array of characters, with just
enough size to hold the string you used as its initializer, and the
program will stop crashing:

% keramida@kobe:/tmp/foo$ c++ -O2 -Wall -fconserve-space -ggdb foo.cc
% keramida@kobe:/tmp/foo$ ./a.out
% Starting
% l=0xbfbfe8a0, pch=0xbfbfe8a5
% hello
% l=0xbfbfe8a0, pch=0xbfbfe8ab
% world
% l=0xbfbfe8a0, pch=0xbfbfe8b0
% this
% l=0xbfbfe8a0, pch=0xbfbfe8b3
% is
% l=0xbfbfe8a0, pch=0xbfbfe8b5
% a
% l=0xbfbfe8a0, pch=0xbfbfe8ba
% test
% Ending
% keramida@kobe:/tmp/foo$

stdazi

unread,
Jan 14, 2007, 7:35:20 AM1/14/07
to

Paul F. Johnson wrote:
> Hi
>
> Måns Rullgård wrote:
>
> >> You've not allocated a memory block to l, so using free is going to cause
> >> undefined behaviour.
> >
> > strdup() allocates memory with malloc(), so free() is perfectly in
> > order there.
>
> Um...
>
> strdup returns a pointer to a new string which is a duplicate of the string
> passed in. Memory for the string is obtained using malloc.
>
> Nowhere in the code is there a malloc - unless I've misunderstood something,
> it's up to the user to do something like
there is a malloc in the code... check the strdup() function.

> char *m = malloc(300) (say)
> m = strdup(foo)

in the above snippet, what's the semantic difference beetwen strdup and
strcpy?

> otherwise all that gets returned into m (without the malloc) is going to be
> gibberish.

DESCRIPTION
The strdup() function returns a pointer to a new string
which is a
duplicate of the string s. Memory for the new string is
obtained with
malloc(3), and can be freed with free(3).

Looks like my man is lying then :-(

Christian Christmann

unread,
Jan 18, 2007, 9:59:31 AM1/18/07
to
>
> % keramida@kobe:/tmp/foo$ c++ -O2 -Wall -fconserve-space -ggdb foo.cc
> % keramida@kobe:/tmp/foo$ ./a.out
> % Starting
> % l=0xbfbfe8a0, pch=0xbfbfe8a5
> % hello
> % l=0xbfbfe8a0, pch=0xbfbfe8ab
> % world
> % l=0xbfbfe8a0, pch=0xbfbfe8b0
> % this
> % l=0xbfbfe8a0, pch=0xbfbfe8b3
> % is
> % l=0xbfbfe8a0, pch=0xbfbfe8b5
> % a
> % l=0xbfbfe8a0, pch=0xbfbfe8ba
> % test
> % Ending
> % keramida@kobe:/tmp/foo$

How do you get this nice output displaying the addresses? When I run my
g++ with "-ggdb", I get the normal program output. Are these any special
flags that must be set up at the compilation of the compiler?


0 new messages