By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,431 Members | 1,845 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,431 IT Pros & Developers. It's quick & easy.

Warnings with gcc

P: n/a
Hello,
I get a warning when I compile:
#include <string.h>

int main (int argc, char ** argv)
{
char * s;
s = strdup("a string");
return 0;
}

with gcc (GCC) 3.3.5 (Debian 1:3.3.5-8ubuntu2) :

$ gcc -Wall -ansi warning.c
warning.c: In function `main':
warning.c:7: warning: implicit declaration of function `strdup'
warning.c:7: warning: assignment makes pointer from integer without a
cast

Does anybody knows how can I supress this warning ?

if I put a cast : s = (char *) strdup("a string");
I get another warning message:
warning.c:7: warning: implicit declaration of function `strdup'

I do not understand why this happens because strdup is declared in
string.h

Thanks,

Thibault Langlois

Nov 23 '05 #1
Share this Question
Share on Google+
34 Replies


P: n/a

<th***************@di.fc.ul.pt> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
Hello,
I get a warning when I compile:
#include <string.h>

int main (int argc, char ** argv)
{
char * s;
s = strdup("a string");
return 0;
}

with gcc (GCC) 3.3.5 (Debian 1:3.3.5-8ubuntu2) :

$ gcc -Wall -ansi warning.c
warning.c: In function `main':
warning.c:7: warning: implicit declaration of function `strdup'
warning.c:7: warning: assignment makes pointer from integer without a
cast

Does anybody knows how can I supress this warning ?

if I put a cast : s = (char *) strdup("a string");
I get another warning message:
warning.c:7: warning: implicit declaration of function `strdup'

I do not understand why this happens because strdup is declared in
string.h


Well, it can't be can it - unless the compiler's wrong?

Have you confirmed that it's in [your] string.h?

Does your preprocessed output contain it?

Does it link?

rayw
Nov 23 '05 #2

P: n/a
th***************@di.fc.ul.pt wrote:
I do not understand why this happens because strdup is declared in
string.h


strdup is not in string.h

news:gnu.gcc

http://www.ungerhu.com/jxh/clc.welcome.txt

--
pete
Nov 23 '05 #3

P: n/a
"th***************@di.fc.ul.pt" <th***************@di.fc.ul.pt> wrote:
I get a warning when I compile:
#include <string.h>

int main (int argc, char ** argv)
{
char * s;
s = strdup("a string");
return 0;
} warning.c:7: warning: implicit declaration of function `strdup'

I do not understand why this happens because strdup is declared in
string.h


strdup() is not ISO C, and should therefore _not_ be declared in
<string.h> in a conforming implementation. Looks like gcc with -ansi is
conforming in this respect (as in most, perhaps all, others).

Richard
Nov 23 '05 #4

P: n/a
th***************@di.fc.ul.pt wrote:
Hello,
I get a warning when I compile:
#include <string.h>

int main (int argc, char ** argv)
this is better than int main () or void main (void) which we see too
often around here, but since you are not using either of these
variables, why not just int main (void)?
{
char * s;
s = strdup("a string");
strdup is not a Standard C function, it is a BSD extension. You
specified the -ansi option when you tried to compile this telling the
compiler you want to compile as a strictly conforming program. This
option defines the macro __STRICT_ANSI__ which will keep the prototype
for strdup from being visible from string.h. You can either remove the
-ansi switch, or place the following define before your include
directive:
#define _GNU_SOURCE
return 0;
}

with gcc (GCC) 3.3.5 (Debian 1:3.3.5-8ubuntu2) :

$ gcc -Wall -ansi warning.c
warning.c: In function `main':
warning.c:7: warning: implicit declaration of function `strdup'
The prototype for strdup is not in scope, hence the diagnostic, see
above.
warning.c:7: warning: assignment makes pointer from integer without a
cast
Since the prototype for strdup is not in scope, the compiler assumes it
returns an int which you are storing into a pointer without a cast,
this is required to produce a diagnostic.
Does anybody knows how can I supress this warning ?
The -w switch turns off all warnings but this justs hides the problem,
fix the issue instead.
if I put a cast : s = (char *) strdup("a string");
I get another warning message:
warning.c:7: warning: implicit declaration of function `strdup'


Since you cast the result of strdup, which the compiler thinks is an
int, to a char * a diagnostic is not required. You still have the
issue of strdup not being declared. If you are using a cast to supress
a compiler diagnostic, this is a good clue you are doing something
wrong.

Robert Gamble

Nov 23 '05 #5

P: n/a

<th***************@di.fc.ul.pt> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
Hello,
I get a warning when I compile:
#include <string.h>

int main (int argc, char ** argv)
{
char * s;
s = strdup("a string");
return 0;
}

with gcc (GCC) 3.3.5 (Debian 1:3.3.5-8ubuntu2) :

$ gcc -Wall -ansi warning.c
warning.c: In function `main':
warning.c:7: warning: implicit declaration of function `strdup'
warning.c:7: warning: assignment makes pointer from integer without a
cast

Does anybody knows how can I supress this warning ?

if I put a cast : s = (char *) strdup("a string");
I get another warning message:
warning.c:7: warning: implicit declaration of function `strdup'

I do not understand why this happens because strdup is declared in
string.h

Thanks,

Thibault Langlois


drop the "-ansi" strdup is a non-ANSI extension (at least according to gcc).

barry
Nov 23 '05 #6

P: n/a
Barry wrote:
<th***************@di.fc.ul.pt> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
I get a warning when I compile:
#include <string.h>

int main (int argc, char ** argv)
{
char * s;
s = strdup("a string");
return 0;
}

with gcc (GCC) 3.3.5 (Debian 1:3.3.5-8ubuntu2) :

$ gcc -Wall -ansi warning.c
warning.c: In function `main':
warning.c:7: warning: implicit declaration of function `strdup'
<snip>
drop the "-ansi" strdup is a non-ANSI extension (at least according to gcc).

That's not quite it. gcc would in fact be allowed to provide strdup()
even in ANSI mode, but it chooses not to, presumably to help people
catch conformance errors (which is -ansi's primary purpose).

(To be even more precise, it actually depends on the standard library
implementation used with gcc.)

S.
Nov 23 '05 #7

P: n/a

"Skarmander" <in*****@dontmailme.com> wrote in message
news:43***********************@news.xs4all.nl...
Barry wrote:
<th***************@di.fc.ul.pt> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
I get a warning when I compile:
#include <string.h>

int main (int argc, char ** argv)
{
char * s;
s = strdup("a string");
return 0;
}

with gcc (GCC) 3.3.5 (Debian 1:3.3.5-8ubuntu2) :

$ gcc -Wall -ansi warning.c
warning.c: In function `main':
warning.c:7: warning: implicit declaration of function `strdup' <snip>

drop the "-ansi" strdup is a non-ANSI extension (at least according to

gcc).

That's not quite it. gcc would in fact be allowed to provide strdup()
even in ANSI mode, but it chooses not to, presumably to help people
catch conformance errors (which is -ansi's primary purpose).

(To be even more precise, it actually depends on the standard library
implementation used with gcc.)

S.


Thanks for the correction. My post was based solely on the comments in the
gcc
header files.

barry
Nov 23 '05 #8

P: n/a
pete wrote:
th***************@di.fc.ul.pt wrote:

I do not understand why this happens because strdup is declared in
string.h

strdup is not in string.h

news:gnu.gcc

http://www.ungerhu.com/jxh/clc.welcome.txt

strdup is in string.h in my linux system with
gcc version 2.96 20000731 (Mandrake Linux 8.2 2.96-0.76mdk)

jacob
Nov 23 '05 #9

P: n/a
jacob navia wrote:
pete wrote:
th***************@di.fc.ul.pt wrote:

I do not understand why this happens because strdup is declared in
string.h


strdup is not in string.h

news:gnu.gcc

http://www.ungerhu.com/jxh/clc.welcome.txt

strdup is in string.h in my linux system with
gcc version 2.96 20000731 (Mandrake Linux 8.2 2.96-0.76mdk)

strdup() is *not necessarily* in string.h. It's a nonstandard function;
the standard doesn't define it. Implementations are allowed to define
additional functions beginning with "str" in <string.h>, however (and if
<string.h> is included, a program may not define such functions).

S.
Nov 23 '05 #10

P: n/a
jacob navia wrote:

pete wrote:

strdup is not in string.h

news:gnu.gcc

http://www.ungerhu.com/jxh/clc.welcome.txt

strdup is in string.h in my linux system with
gcc version 2.96 20000731 (Mandrake Linux 8.2 2.96-0.76mdk)


Maybe there's a newsgroup or two,
listed in the above quoted URL,
where that's on topic.

--
pete
Nov 23 '05 #11

P: n/a
In article <43**********************@news.wanadoo.fr> jacob navia <ja***@jacob.remcomp.fr> writes:
....
strdup is in string.h in my linux system with
gcc version 2.96 20000731 (Mandrake Linux 8.2 2.96-0.76mdk)


Unconditional? strdup is also in string.h here (Solaris), as follows:

#if defined(__EXTENSIONS__) || (__STDC__ == 0 && \
!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || \
defined(_XPG4_2)
extern char *strdup(const char *);
#endif

--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 23 '05 #12

P: n/a
th***************@di.fc.ul.pt wrote:
Hello,
I get a warning when I compile:
#include <string.h>

int main (int argc, char ** argv)
{
char * s;
s = strdup("a string");
return 0;
}
You should. strdup() isn't an ansi compliant function.

Does anybody knows how can I supress this warning ?
Don't use strdup()
I do not understand why this happens because strdup is declared in
string.h


Because you told gcc when using the -ansi directive.

Igmar
Nov 23 '05 #13

P: n/a
Skarmander wrote:

<snip>
strdup() is *not necessarily* in string.h. It's a nonstandard function;
the standard doesn't define it. Implementations are allowed to define
additional functions beginning with "str" in <string.h>, however (and if
<string.h> is included, a program may not define such functions).


We've had this discussion here before, and not too many weeks back IIRC.
programs are not allowed to declare such identifiers with external
linkage even if they *don't* include string.h
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 23 '05 #14

P: n/a
On 2005-11-22, Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Skarmander wrote:

<snip>
strdup() is *not necessarily* in string.h. It's a nonstandard function;
the standard doesn't define it. Implementations are allowed to define
additional functions beginning with "str" in <string.h>, however (and if
<string.h> is included, a program may not define such functions).


We've had this discussion here before, and not too many weeks back IIRC.
programs are not allowed to declare such identifiers with external
linkage even if they *don't* include string.h


What about with static linkage?

[incidentally, stdlib.h as well as string.h for the 'str' prefix]
Nov 23 '05 #15

P: n/a
Flash Gordon wrote:
Skarmander wrote:

<snip>
strdup() is *not necessarily* in string.h. It's a nonstandard
function; the standard doesn't define it. Implementations are allowed
to define additional functions beginning with "str" in <string.h>,
however (and if <string.h> is included, a program may not define such
functions).

We've had this discussion here before, and not too many weeks back IIRC.
programs are not allowed to declare such identifiers with external
linkage even if they *don't* include string.h


That's quite possible. I didn't mean to imply otherwise. They are
unambiguously not allowed to declare such functions regardless of
linkage if <string.h> *is* included, and that is all I said.

S.
Nov 23 '05 #16

P: n/a
Thank you (and all other posters) for your answer.
I found that using -sdt=gnu99 instead of -ansi is enough to supress the
warning.

I am a bit confused by ansi/iso features and someone may be kind engouh
to explain me or give some pointers where I can find the information.
1. The ansi/iso standards are about the language itself or about the
what K&R call the "standard library" ? or both ?
2. My source of info is the K&R book, the edition with the "ansi C" on
the cover. In the appendix the authors write about the "Standard
Library ... defined by the ANSI standard". The say also : "The standard
liabrary is not part of the C language proper but an environment that
supports the standard C and will provide the function declarations
[...] of this library."
Among the standard headers there is the string.h that should contain
strdup().
That is why I was expecting that -ansi would not cause such warnings.
Is it a gcc-specific feature/bug ?

Thibault Langlois

Nov 23 '05 #17

P: n/a
th***************@di.fc.ul.pt wrote:
Thank you (and all other posters) for your answer.
I found that using -sdt=gnu99 instead of -ansi is enough to supress the
warning.
This does not "suppress" the warning, actually, because with -std=gnu99,
strdup() is defined by <string.h>. Using -std=gnu99 enables many other
features that are not part of standard C, by the way.
I am a bit confused by ansi/iso features and someone may be kind engouh
to explain me or give some pointers where I can find the information.
1. The ansi/iso standards are about the language itself or about the
what K&R call the "standard library" ? or both ?
Both.
2. My source of info is the K&R book, the edition with the "ansi C" on
the cover. In the appendix the authors write about the "Standard
Library ... defined by the ANSI standard". The say also : "The standard
liabrary is not part of the C language proper but an environment that
supports the standard C and will provide the function declarations
[...] of this library."
And that's right. It's not part of the language proper, but the standard
covers conforming implementations of C environments. That includes the
library.
Among the standard headers there is the string.h that should contain
strdup().
No. If K&R says this, it's wrong. But read carefully if that's what's
really said.
That is why I was expecting that -ansi would not cause such warnings.
Is it a gcc-specific feature/bug ?

Not really. strdup() doesn't have to exist, period. If your
implementation provides it, that's nice. Relying on its existence makes
your program unportable to platforms that don't have it.

strdup() is actually defined by the POSIX standard and it is available
on many platforms, it's just not part of ANSI C.

S.
Nov 23 '05 #18

P: n/a
Jordan Abel wrote:
On 2005-11-22, Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Skarmander wrote:

<snip>
strdup() is *not necessarily* in string.h. It's a nonstandard function;
the standard doesn't define it. Implementations are allowed to define
additional functions beginning with "str" in <string.h>, however (and if
<string.h> is included, a program may not define such functions). We've had this discussion here before, and not too many weeks back IIRC.
programs are not allowed to declare such identifiers with external
linkage even if they *don't* include string.h


What about with static linkage?


The relevant part of section 7.1.3 from N1124 is:
| All identifiers with external linkage in any of the following
| subclauses (including the future library directions) are always
| reserved for use as identifiers with external linkage.157)
| Each identifier with file scope listed in any of the following
| subclauses (including the future library directions) is reserved for
| use as a macro name and as an identifier with file scope in the same
| name space if any of its associated headers is included.

So I would say that you can have:
static int strcpy(void) {return 0};
if you want and have not included string.h or stdlib.h
[incidentally, stdlib.h as well as string.h for the 'str' prefix]


Yes, you are correct. str[a-z] are reserved if you include stdlib.h
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 23 '05 #19

P: n/a
Skarmander wrote:
Flash Gordon wrote:
Skarmander wrote:

<snip>
strdup() is *not necessarily* in string.h. It's a nonstandard
function; the standard doesn't define it. Implementations are allowed
to define additional functions beginning with "str" in <string.h>,
however (and if <string.h> is included, a program may not define such
functions).


We've had this discussion here before, and not too many weeks back
IIRC. programs are not allowed to declare such identifiers with
external linkage even if they *don't* include string.h


That's quite possible. I didn't mean to imply otherwise. They are
unambiguously not allowed to declare such functions regardless of
linkage if <string.h> *is* included, and that is all I said.


OK, it's just that the way you worded it someone might think that if
they did not include string.h they could declare their own external
objects with such names.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 23 '05 #20

P: n/a
jacob navia wrote
(in article <43**********************@news.wanadoo.fr>):
pete wrote:
th***************@di.fc.ul.pt wrote:

I do not understand why this happens because strdup is declared in
string.h

strdup is not in string.h

news:gnu.gcc

http://www.ungerhu.com/jxh/clc.welcome.txt

strdup is in string.h in my linux system with
gcc version 2.96 20000731 (Mandrake Linux 8.2 2.96-0.76mdk)


By now you should know very well why this is an issue,
particularly in clc. I suspect you do, but intentionally don't
mention it. Disappointing.
--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Nov 23 '05 #21

P: n/a
"th***************@di.fc.ul.pt" <th***************@di.fc.ul.pt> writes:
Hello,
I get a warning when I compile:
#include <string.h>

int main (int argc, char ** argv)
{
char * s;
s = strdup("a string");
return 0;
}


As others have mentioned, strdup() is not a standard C function. If
you want to maximize the portability of your code, it's easy enough
to roll your own:

char *dupstr(const char *s)
{
char *result = malloc(strlen(s) + 1);
if (result != NULL) {
strcpy(s, result);
}
return result;
}

(This requires #include directives for <string.h> and <stdlib.h>.)

On the other hand, strdup() is part of the POSIX standard. If you're
already using other POSIX-specific features that aren't part of
standard C, you might as well use strdup() as well; just don't tell
your compiler to restrict itself to strict ANSI/ISO C.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 23 '05 #22

P: n/a
On 2005-11-22, Keith Thompson <ks***@mib.org> wrote:
"th***************@di.fc.ul.pt" <th***************@di.fc.ul.pt> writes:
Hello,
I get a warning when I compile:
#include <string.h>

int main (int argc, char ** argv)
{
char * s;
s = strdup("a string");
return 0;
}


As others have mentioned, strdup() is not a standard C function. If
you want to maximize the portability of your code, it's easy enough
to roll your own:

char *dupstr(const char *s)
{
char *result = malloc(strlen(s) + 1);
if (result != NULL) {
strcpy(s, result);
}
return result;
}


Note that storing the length and using memcpy may be more efficient.
this is also what freebsd does for strdup. This also accounts for the
[dubious] possibility that the length of the string may overflow size_t.
Nov 23 '05 #23

P: n/a
Jordan Abel <jm****@purdue.edu> writes:
On 2005-11-22, Keith Thompson <ks***@mib.org> wrote:

[...]
As others have mentioned, strdup() is not a standard C function. If
you want to maximize the portability of your code, it's easy enough
to roll your own:

char *dupstr(const char *s)
{
char *result = malloc(strlen(s) + 1);
if (result != NULL) {
strcpy(s, result);
}
return result;
}


Note that storing the length and using memcpy may be more efficient.
this is also what freebsd does for strdup. This also accounts for the
[dubious] possibility that the length of the string may overflow size_t.


It might be more efficient, but there's no *fundamental* reason to
expect that it will be. Both strcpy() and memcpy() do a linear (O(1))
scan of the input string; strcpy() looks for a '\0' character, and
memcpy() scans until it's copied the specified number of bytes.

I suppose strcpy() might be slower because it has to examine each
byte, and accessing a byte might be slower than testing a word-sized
counter. Also, memcpy() might be optimized in ways that strcpy()
might not be, for example copying a word at a time rather than a byte
at a time.

There are cases where scanning to the end of a string looking for the
'\0' is clearly less efficient than an alternative, such as building
up a string with multiple calls to strcat(). This isn't one of them;
the performance issues here are more subtle.

This could be an argument in favor of using the system-provided
strdup() function, if there is one, since it might be optimized for
the underlying hardware in ways that a portable implementation can't
be.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 23 '05 #24

P: n/a
On Tue, 22 Nov 2005 14:15:14 +0100, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.fr> wrote:
strdup is in string.h in my linux system with
gcc version 2.96


In order for this implementation to conform, compilation with strict
ISO compatibility would have to exclude the declaration.

As indeed it does - which is why the OP has the problem he does.

Its also why posting platform-specific answers here is a bad idea.
Your post can only have further confused the OP. Jacob, please take
note of this.
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Nov 23 '05 #25

P: n/a
On Tue, 22 Nov 2005 20:40:19 +0000, Jordan Abel wrote:
[dubious] possibility that the length of the string may overflow size_t.


I don't believe it's possible to portably construct a string whose length
overflows size_t. How would you do it?

--
http://members.dodo.com.au/~netocrat
Nov 23 '05 #26

P: n/a
Netocrat wrote:

On Tue, 22 Nov 2005 20:40:19 +0000, Jordan Abel wrote:
[dubious] possibility that the
length of the string may overflow size_t.


I don't believe it's possible to
portably construct a string whose length
overflows size_t. How would you do it?


Portably? You can't.

The description of the standard string functions
is that they are for:
"manipulating arrays of character type and other
objects treated as arrays of character type."
.... despite the fact
that the definition of "string" is broader than that.

I don't see much point in worrying about strings
longer than (size_t)-1.

--
pete
Nov 23 '05 #27

P: n/a
Netocrat wrote:
On Tue, 22 Nov 2005 20:40:19 +0000, Jordan Abel wrote:
[dubious] possibility that the length of the string may overflow size_t.


I don't believe it's possible to portably construct a string whose length
overflows size_t. How would you do it?


Untested:
#include <stdlib.h>

#define BIGNUM1 32767
#define BIGNUM2 32767

int main(void)
{
unsigned long i,j;
char *bigstring=calloc(BIGNUM1,BIGNUM2);
char *ptr=bigstring;
if (bigstring) {
for (i=1; i<BIGNUM1; i++) {
for (j=0; j<(i==BIGNUM1)?BIGNUM2-1:BIGNUM2; j++) {
*ptr++ = 'A';
}
}
/* do whatever */
free(bigstring);
}
}

No guarantee you this will actually generate such a string, since in all
probability calloc will fail, but with suitable values of BIGNUM1 and
BIGNUM2 for your system I believe the above could theoretically generate
a string with a length greater than size_t.

For the best chance you want to try and allocate only just enough space
for it to be larger than can be expressed in size_t.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 23 '05 #28

P: n/a
pete <pf*****@mindspring.com> wrote:
Netocrat wrote:

On Tue, 22 Nov 2005 20:40:19 +0000, Jordan Abel wrote:
> [dubious] possibility that the
> length of the string may overflow size_t.


I don't believe it's possible to
portably construct a string whose length
overflows size_t. How would you do it?


Portably? You can't.

The description of the standard string functions
is that they are for:
"manipulating arrays of character type and other
objects treated as arrays of character type."
... despite the fact
that the definition of "string" is broader than that.

I don't see much point in worrying about strings
longer than (size_t)-1.

#include <...>
char *p = calloc(2, SIZE_MAX);
assert(p);
for (p1=p, i=0; i<2; ++i)
for (j=0; j<SIZE_MAX; ++j)
if (!(i == 1 && j == SIZE_MAX-1))
*p1++ = 'x';
/*code not checked, but you get the idea*/
strlen(p); /* ??? */

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 23 '05 #29

P: n/a
On Wed, 23 Nov 2005 13:33:44 +0000, Flash Gordon wrote:
Netocrat wrote:
On Tue, 22 Nov 2005 20:40:19 +0000, Jordan Abel wrote:
[dubious] possibility that the length of the string may overflow size_t.
I don't believe it's possible to portably construct a string whose length
overflows size_t. How would you do it?


Untested:
#include <stdlib.h>

#define BIGNUM1 32767
#define BIGNUM2 32767


You presumably intend that SIZE_MAX is equal to or only slightly larger
than 32767.
int main(void)
{
unsigned long i,j;
char *bigstring=calloc(BIGNUM1,BIGNUM2);

char *ptr=bigstring;
if (bigstring) {
for (i=1; i<BIGNUM1; i++) {
for (j=0; j<(i==BIGNUM1)?BIGNUM2-1:BIGNUM2; j++) {
*ptr++ = 'A';
calloc returns an array of objects. This code treats that array as a
single object, but pointer arithmetic is only defined within an object (or
one past the end).

That can be easily solved using indexing instead of pointer arithmetic:

bigstring[i][j] = 'A';
}
}
/* do whatever */
free(bigstring);
}
}

No guarantee you this will actually generate such a string, since in all
probability calloc will fail, but with suitable values of BIGNUM1 and
BIGNUM2 for your system I believe the above could theoretically generate
a string with a length greater than size_t.
Pete's already pointed out that the functions of <string.h> operate on
arrays of character type.

Aside from that, there's defect report #266
(http://www.open-std.org/jtc1/sc22/wg...ocs/dr_266.htm) which deals
with sizeof applied to a static two-dimensional array of size greater than
SIZE_MAX and concludes that "The program is not strictly conforming
because it exceeds an environmental limit."

Looking at the description of strlen in both C89 and C99 drafts, I see no
mention of how strings with length greater than SIZE_MAX are dealt with,
so I imagine that the same reasoning would apply. Such a string would
violate an environmental limit.
For the best chance you want to try and allocate only just enough space
for it to be larger than can be expressed in size_t.


--
http://members.dodo.com.au/~netocrat
Nov 23 '05 #30

P: n/a
Netocrat wrote:
On Wed, 23 Nov 2005 13:33:44 +0000, Flash Gordon wrote:
Netocrat wrote:
On Tue, 22 Nov 2005 20:40:19 +0000, Jordan Abel wrote:

[dubious] possibility that the length of the string may overflow size_t.
I don't believe it's possible to portably construct a string whose length
overflows size_t. How would you do it? Untested:
#include <stdlib.h>

#define BIGNUM1 32767
#define BIGNUM2 32767


You presumably intend that SIZE_MAX is equal to or only slightly larger
than 32767.


Did C89 have SIZE_MAX? I could not see it mentioned in my copy of K&R2.
Anyway, I intend for the *product* of the two numbers to be slightly
larger than SIZE_MAX, so select them appropriately for your environment.
int main(void)
{
unsigned long i,j;
char *bigstring=calloc(BIGNUM1,BIGNUM2);

char *ptr=bigstring;
if (bigstring) {
for (i=1; i<BIGNUM1; i++) {
for (j=0; j<(i==BIGNUM1)?BIGNUM2-1:BIGNUM2; j++) {
*ptr++ = 'A';


calloc returns an array of objects. This code treats that array as a
single object, but pointer arithmetic is only defined within an object (or
one past the end).


I believe that is not a problem for a char pointer. An array is an
object and you can use a char pointer to step through any object. Note
the definition of object in the standard, which is, "region of data
storage in the execution environment, the contents of which can
represent values" which, as far as I can see, applies to the region of
data storage the pointer returned by calloc.
That can be easily solved using indexing instead of pointer arithmetic:

bigstring[i][j] = 'A';
This would require changing the type of bigstring.
}
}
/* do whatever */
free(bigstring);
}
}

No guarantee you this will actually generate such a string, since in all
probability calloc will fail, but with suitable values of BIGNUM1 and
BIGNUM2 for your system I believe the above could theoretically generate
a string with a length greater than size_t.


Pete's already pointed out that the functions of <string.h> operate on
arrays of character type.


The definition of string I can see in section 7.1.1 of N1124 does not
mention arrays, it says:
| A string is a contiguous sequence of characters terminated by and
| including the first null character. The term multibyte string is
| sometimes used instead to emphasize special processing given to
| multibyte characters contained in the string or to avoid confusion
| with a wide string. A pointer to a string is a pointer to its initial
| (lowest addressed) character. The length of a string is the number of
| bytes preceding the null character and the value of a string is the
| sequence of the values of the contained characters, in order.

What I generate above meets that definition as far as I can see.
Aside from that, there's defect report #266
(http://www.open-std.org/jtc1/sc22/wg...ocs/dr_266.htm) which deals
with sizeof applied to a static two-dimensional array of size greater than
SIZE_MAX and concludes that "The program is not strictly conforming
because it exceeds an environmental limit."
Definitely true if you use a declared array rather than a calloced
block. I would also argue that as an array is an object (see my
arguments above) it also applies to a block created by calloc.
Looking at the description of strlen in both C89 and C99 drafts, I see no
mention of how strings with length greater than SIZE_MAX are dealt with,
so I imagine that the same reasoning would apply. Such a string would
violate an environmental limit.


Either that or it is undefined behaviour "by the omission of any xplicit
definition of behavior." if you pass such a string to strlen or one of
the other functions that returns an index of type size_t. However, your
suggestion of exceeding an environmental limit would also, IMHO, apply
to my call to calloc.
For the best chance you want to try and allocate only just enough space
for it to be larger than can be expressed in size_t.


I should have put the above by where I devined the constants, rather
than down here.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 23 '05 #31

P: n/a
[can a string with length > SIZE_MAX be portably created; and if so what
is the result of calling strlen on it]

On Wed, 23 Nov 2005 20:23:42 +0000, Flash Gordon wrote:
Netocrat wrote:
On Wed, 23 Nov 2005 13:33:44 +0000, Flash Gordon wrote:
Untested:
#include <stdlib.h>

#define BIGNUM1 32767
#define BIGNUM2 32767 [whose product is intended to be greater than SIZE_MAX]
Did C89 have SIZE_MAX?
It did not.
int main(void)
{
unsigned long i,j;
char *bigstring=calloc(BIGNUM1,BIGNUM2);

char *ptr=bigstring;
if (bigstring) {
for (i=1; i<BIGNUM1; i++) {
for (j=0; j<(i==BIGNUM1)?BIGNUM2-1:BIGNUM2; j++) {
*ptr++ = 'A';


calloc returns an array of objects. This code treats that array as a
single object, but pointer arithmetic is only defined within an object (or
one past the end).


I believe that is not a problem for a char pointer.


N1124, 6.5.6#8 (on pointer arithmetic)

| If both the pointer operand and the result point to elements of the
| same array object, or one past the last element of the array object,
| the evaluation shall not produce an overflow; otherwise, the
| behavior is undefined. If the result points one past the last
| element of the array object, it shall not be used as the operand of a
| unary * operator that is evaluated.

The "array object" is an array of char (the type to which ptr points),
whereas calloc returns an array of arrays of char. As soon as the ptr
reaches one beyond the end of the first array and is dereferenced, it
is breaking the "shall" condition; and once it reaches two beyond the
end of the first array, it is explicitly undefined behaviour.
An array is an
object and you can use a char pointer to step through any object.
C&V?

[calloc returns an object]

Agreed.
That can be easily solved using indexing instead of pointer arithmetic:

bigstring[i][j] = 'A';


This would require changing the type of bigstring.


Right: char (*bigstring)[BIGNUM2];
}
}
/* do whatever */
free(bigstring);
}
}
No guarantee you this will actually generate such a string, since in
all probability calloc will fail, but with suitable values of BIGNUM1
and BIGNUM2 for your system I believe the above could theoretically
generate a string with a length greater than size_t.


Pete's already pointed out that the functions of <string.h> operate on
arrays of character type.


The definition of string I can see in section 7.1.1 of N1124 does not
mention arrays,

[quote omitted] What I generate above meets that definition as far as I can see.
Agreed, and the quote pete referred to allows for "objects treated as
arrays of char type".
Aside from that, there's defect report #266
(http://www.open-std.org/jtc1/sc22/wg...ocs/dr_266.htm) which
deals with sizeof applied to a static two-dimensional array of size
greater than SIZE_MAX and concludes that "The program is not strictly
conforming because it exceeds an environmental limit."


Definitely true if you use a declared array rather than a calloced
block. I would also argue that as an array is an object (see my
arguments above) it also applies to a block created by calloc.


Although the DR's conclusion also says:

| Translation limits do not apply to objects whose size is determined
| at runtime.
Looking at the description of strlen in both C89 and C99 drafts, I see
no mention of how strings with length greater than SIZE_MAX are dealt
with, so I imagine that the same reasoning would apply. Such a string
would violate an environmental limit.


Either that or it is undefined behaviour "by the omission of any xplicit
definition of behavior."


That seems like better reasoning given what I quoted above from the DR re
translation limits not applying to runtime objects.
if you pass such a string to strlen or one of
the other functions that returns an index of type size_t. However, your
suggestion of exceeding an environmental limit would also, IMHO, apply
to my call to calloc.


The standard doesn't seem to require it; likewise DR 266. Regarding the
result of applying sizeof to such an oversize (determined at runtime)
object, the DR seems to say nothing though.

[...]
--
http://members.dodo.com.au/~netocrat
Nov 24 '05 #32

P: n/a
Netocrat wrote:
[can a string with length > SIZE_MAX be portably created; and if so what
is the result of calling strlen on it]

On Wed, 23 Nov 2005 20:23:42 +0000, Flash Gordon wrote:
Netocrat wrote:
On Wed, 23 Nov 2005 13:33:44 +0000, Flash Gordon wrote:
Untested:
#include <stdlib.h>

#define BIGNUM1 32767
#define BIGNUM2 32767 [whose product is intended to be greater than SIZE_MAX]
Did C89 have SIZE_MAX?
It did not.


That's what I thought, and why I did not use it.
int main(void)
{
unsigned long i,j;
char *bigstring=calloc(BIGNUM1,BIGNUM2);

char *ptr=bigstring;
if (bigstring) {
for (i=1; i<BIGNUM1; i++) {
for (j=0; j<(i==BIGNUM1)?BIGNUM2-1:BIGNUM2; j++) {
*ptr++ = 'A';
calloc returns an array of objects. This code treats that array as a
single object, but pointer arithmetic is only defined within an object (or
one past the end).

I believe that is not a problem for a char pointer.


N1124, 6.5.6#8 (on pointer arithmetic)

| If both the pointer operand and the result point to elements of the
| same array object, or one past the last element of the array object,
| the evaluation shall not produce an overflow; otherwise, the
| behavior is undefined. If the result points one past the last
| element of the array object, it shall not be used as the operand of a
| unary * operator that is evaluated.

The "array object" is an array of char (the type to which ptr points),
whereas calloc returns an array of arrays of char. As soon as the ptr
reaches one beyond the end of the first array and is dereferenced, it
is breaking the "shall" condition; and once it reaches two beyond the
end of the first array, it is explicitly undefined behaviour.


I disagree because an array is an object so this applies from N1124,
6.3.2.3 Pointers:
| 7 A pointer to an object or incomplete type may be converted to a
| pointer to a different object or incomplete type. If the resulting
| pointer is not correctly aligned57) for the pointed-to type, the
| behavior is undefined. Otherwise, when converted back again, the
| result shall compare equal to the original pointer. When a pointer
| to an object is converted to a pointer to a character type, the
| result points to the lowest addressed byte of the object. Successive
| increments of the result, up to the size of the object, yield
| pointers to the remaining bytes of the object.
An array is an
object and you can use a char pointer to step through any object.


C&V?


See above, and the definition of an object in N1124, 3.14:
| object
| region of data storage in the execution environment, the contents of
| which can represent values
[calloc returns an object]

Agreed.


Since you agree calloc returns an object, 6.3.2.3 applies when you
convert it to a pointer to a character type.

<snip>
Aside from that, there's defect report #266
(http://www.open-std.org/jtc1/sc22/wg...ocs/dr_266.htm) which
deals with sizeof applied to a static two-dimensional array of size
greater than SIZE_MAX and concludes that "The program is not strictly
conforming because it exceeds an environmental limit."

Definitely true if you use a declared array rather than a calloced
block. I would also argue that as an array is an object (see my
arguments above) it also applies to a block created by calloc.


Although the DR's conclusion also says:

| Translation limits do not apply to objects whose size is determined
| at runtime.


Ah well.
Looking at the description of strlen in both C89 and C99 drafts, I see
no mention of how strings with length greater than SIZE_MAX are dealt
with, so I imagine that the same reasoning would apply. Such a string
would violate an environmental limit.

Either that or it is undefined behaviour "by the omission of any xplicit
definition of behavior."


That seems like better reasoning given what I quoted above from the DR re
translation limits not applying to runtime objects.


Indeed, which is why I mentioned it :-)
if you pass such a string to strlen or one of
the other functions that returns an index of type size_t. However, your
suggestion of exceeding an environmental limit would also, IMHO, apply
to my call to calloc.


The standard doesn't seem to require it; likewise DR 266. Regarding the
result of applying sizeof to such an oversize (determined at runtime)
object, the DR seems to say nothing though.


Well then, if that is the case then I would guess the calloc call is
required to fail or return a block that could be used for an oversize
string, it's just that functions line strlen are not required to work
this the oversize string.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 24 '05 #33

P: n/a
On Thu, 24 Nov 2005 19:39:22 +0000, Flash Gordon wrote:
Netocrat wrote: [which part of the standard legitimises stepping with a char pointer
through memory returned by a call to calloc with two non-zero arguments?]
[...] Since you agree calloc returns an object, 6.3.2.3 applies when you
convert it to a pointer to a character type.
That's what I was looking for.

[...] I would guess the calloc call is
required to fail or return a block that could be used for an oversize
string, it's just that functions line strlen are not required to work
this the oversize string.


So Jordan's advice was sound (use memcpy rather than strcpy after
malloc'ing memory based on the return of strlen).

--
http://members.dodo.com.au/~netocrat
Nov 25 '05 #34

P: n/a
Netocrat wrote:
On Thu, 24 Nov 2005 19:39:22 +0000, Flash Gordon wrote:
Netocrat wrote: [which part of the standard legitimises stepping with a char pointer
through memory returned by a call to calloc with two non-zero arguments?]
[...]
Since you agree calloc returns an object, 6.3.2.3 applies when you
convert it to a pointer to a character type.


That's what I was looking for.


:-)
[...]
I would guess the calloc call is
required to fail or return a block that could be used for an oversize
string, it's just that functions line strlen are not required to work
this the oversize string.


So Jordan's advice was sound (use memcpy rather than strcpy after
malloc'ing memory based on the return of strlen).


Indeed.

It's my habit in any case, because of the processors I've used where
memcpy could be implemented significantly more efficiently than strcpy
(you could tell the processor to repeat the next instruction n times,
with the next instruction being copy a byte, and where a byte was the
same size as the data bus). No guarantee that it is more efficient on
other processors of course, or even on that processor (the
implementation is allowed to provide a needlessly inefficient memcpy),
but it is why I developed the habit of always using memcpy IF I know in
advance how much data is available to copy, even when copying strings.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 25 '05 #35

This discussion thread is closed

Replies have been disabled for this discussion.