Issue with printing a string

S

Seebs

What about the stdcall ABI, when you don't do fancy linking based on
the parameter list? The callee will end up popping either too few or
too many arguments from the stack.

I have apparently never used it, or if I have, I never happen to have seen
something with the wrong number of arguments in it.

-s
 
D

Default User

Michael said:
Worth putting effort into, nonetheless. Trolls get tired, grow up, or
die, eventually.

They get tired much faster if you ignore them.




Brian
 
P

Phil Carmody

Andrew Poelstra said:
char RandomChar() {
static char src[] = "acbdefghijklmnopqrstuvwxyz";
return src[rand() % sizeof src];
}
I doubt you want exactly this. You probably want to use

rand() % (sizeof src - 1)
Oh my goodness! I did mean that, and I have been bitten
by this bug in my own code. (Though in that case, it was
a one-off password generator and as I recall I just kept
running it until I got a string without any \0 characters
truncating the string.)

I mention in passing that gcc (4.1 here), even with no
optimisation, turns strlen(src) into a constant. I'd feel
a bit odd relying on that, but it's nice to know that at
least on the only compiler I regularly use (modulo a whole
host of different versions), can be relied on to turn the
apparently inefficient into the optimal.

Phil
 
S

Seebs

I mention in passing that gcc (4.1 here), even with no
optimisation, turns strlen(src) into a constant. I'd feel
a bit odd relying on that, but it's nice to know that at
least on the only compiler I regularly use (modulo a whole
host of different versions), can be relied on to turn the
apparently inefficient into the optimal.

This actually bit us once. There's another rule:
strcpy(dest, "string literal");
is magically transformed into
memcpy(dest, "string literal", 15);

But. In one of the branches of the Linux kernel tree, someone thought it
would be a great idea to provide a special hand-tuned assembly implementation
of memcpy, which saved a single instruction by returning 0 instead of the
destination pointer.

Enter a lump of code roughly to the effect of:
strcat(strcpy(dest, "foo"), "bar");
and a kernel panic as strcat tried to copy into a null pointer.

After some consideration, we determined that this did not constitute a
toolchain bug.

(The question isn't as trivial as it might seem, because freestanding
environments are in some cases permitted to have a really weird standard
library. There is an option to disable that transformation, but it seemed
smarter to just fix the memcpy() implementation.)

-s
 
A

Andrew Poelstra

Andrew Poelstra said:
char RandomChar() {
static char src[] = "acbdefghijklmnopqrstuvwxyz";
return src[rand() % sizeof src];
}
I doubt you want exactly this. You probably want to use

rand() % (sizeof src - 1)
Oh my goodness! I did mean that, and I have been bitten
by this bug in my own code. (Though in that case, it was
a one-off password generator and as I recall I just kept
running it until I got a string without any \0 characters
truncating the string.)

I mention in passing that gcc (4.1 here), even with no
optimisation, turns strlen(src) into a constant. I'd feel
a bit odd relying on that, but it's nice to know that at
least on the only compiler I regularly use (modulo a whole
host of different versions), can be relied on to turn the
apparently inefficient into the optimal.

Out of curiousity, what disassembler do you use to tell that?
 
I

Ian Collins

Phil said:
I mention in passing that gcc (4.1 here), even with no
optimisation, turns strlen(src) into a constant. I'd feel
a bit odd relying on that, but it's nice to know that at
least on the only compiler I regularly use (modulo a whole
host of different versions), can be relied on to turn the
apparently inefficient into the optimal.

Sun cc will do the same, very handy. I guess anywhere the programmer
could use sizeof in place of strlen, the compiler does the same.
 
E

Ersek, Laszlo

Out of curiousity, what disassembler do you use to tell that?

Probably no disassembler, just "gcc -S":

http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Overall-Options.html#index-S-75

It works here too (4.3.2):

----v----
#include <string.h>
int main(void)
{
return strlen("The quick brown fox jumps over the lazy dog");
}
----^----

$ gcc -S strlen.c

----v----
main:
..LFB2:
pushq %rbp
..LCFI0:
movq %rsp, %rbp
..LCFI1:
movl $43, %eax
leave
ret
----^----

Cheers,
lacos
 
P

Phil Carmody

Andrew Poelstra said:
Andrew Poelstra said:
char RandomChar() {
static char src[] = "acbdefghijklmnopqrstuvwxyz";
return src[rand() % sizeof src];
}
I doubt you want exactly this. You probably want to use

rand() % (sizeof src - 1)
Oh my goodness! I did mean that, and I have been bitten
by this bug in my own code. (Though in that case, it was
a one-off password generator and as I recall I just kept
running it until I got a string without any \0 characters
truncating the string.)

I mention in passing that gcc (4.1 here), even with no
optimisation, turns strlen(src) into a constant. I'd feel
a bit odd relying on that, but it's nice to know that at
least on the only compiler I regularly use (modulo a whole
host of different versions), can be relied on to turn the
apparently inefficient into the optimal.
Out of curiousity, what disassembler do you use to tell that?

I didn't.

Phil
(more in headers, but please think before looking)
 
N

Nobody

I mention in passing that gcc (4.1 here), even with no
optimisation, turns strlen(src) into a constant.

Are you quite sure it's gcc?

glibc's <string.h> includes <bits/string.h>, which has a whole host of
macros and inline asm. The actual strcpy() macro is:

#define strcpy(dest, src) \
(__extension__ (__builtin_constant_p (src) \
? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \
? __strcpy_a_small ((dest), (src), strlen (src) + 1) \
: (char *) memcpy ((char *) (dest), \
(__const char *) (src), \
strlen (src) + 1)) \
: __strcpy_g ((dest), (src))))

Try the test again with "#undef strcpy".
 
N

Nobody

But it must move the stack pointer? Otherwise recursion would
be very difficult.

For the cdecl calling convention, the caller adjusts ESP prior to the
call (either explicitly or by PUSHing the arguments), then restores it
upon return. The two will always cancel each other out, regardless of
whether the arguments are correct for the function being called.
 
P

Phil Carmody

Nobody said:
Are you quite sure it's gcc?

No. I just hammered randomly on the keys and ran a random program
instead of the compiler. Looking at my command-line history, it
appears I ran 'rm' instead, so I can't even tell you what code
it actually was 'compiling'.
glibc's <string.h> includes <bits/string.h>, which has a whole host of
macros and inline asm. The actual strcpy() macro is:

#define strcpy(dest, src) \
(__extension__ (__builtin_constant_p (src) \
? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \
? __strcpy_a_small ((dest), (src), strlen (src) + 1) \
: (char *) memcpy ((char *) (dest), \
(__const char *) (src), \
strlen (src) + 1)) \
: __strcpy_g ((dest), (src))))

Try the test again with "#undef strcpy".

Nice hatstand, Roger.

Phil
 
F

Flash Gordon

Phil said:
No. I just hammered randomly on the keys and ran a random program
instead of the compiler. Looking at my command-line history, it
appears I ran 'rm' instead, so I can't even tell you what code
it actually was 'compiling'.

It wasn't a daft question.
glibc's <string.h> includes <bits/string.h>, which has a whole host of
macros and inline asm. The actual strcpy() macro is:

#define strcpy(dest, src) \
(__extension__ (__builtin_constant_p (src) \
? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \
? __strcpy_a_small ((dest), (src), strlen (src) + 1) \
: (char *) memcpy ((char *) (dest), \
(__const char *) (src), \
strlen (src) + 1)) \
: __strcpy_g ((dest), (src))))

Try the test again with "#undef strcpy".

Nice hatstand, Roger.

It shows that it could well have been glibc rather than gcc which was
responsible for the transformation.
 
P

Phil Carmody

Flash Gordon said:
It wasn't a daft question.

Opinions may vary.
glibc's <string.h> includes <bits/string.h>, which has a whole host of
macros and inline asm. The actual strcpy() macro is:

#define strcpy(dest, src) \
(__extension__ (__builtin_constant_p (src) \
? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \
? __strcpy_a_small ((dest), (src), strlen (src) + 1) \
: (char *) memcpy ((char *) (dest), \
(__const char *) (src), \
strlen (src) + 1)) \
: __strcpy_g ((dest), (src))))

Try the test again with "#undef strcpy".

Nice hatstand, Roger.

It shows that it could well have been glibc rather than gcc which was
responsible for the transformation.

The only thing which could transform strlen() to strcpy() would be gbugc.

Phil
 
N

Nobody

I mention in passing that gcc (4.1 here), even with no
optimisation, turns strlen(src) into a constant.

Are you quite sure it's gcc?

glibc's <string.h> includes <bits/string.h>, which has a whole host of
macros and inline asm. The actual strcpy() macro is:

#define strcpy(dest, src) \
(__extension__ (__builtin_constant_p (src) \
? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \
? __strcpy_a_small ((dest), (src), strlen (src) + 1) \
: (char *) memcpy ((char *) (dest), \
(__const char *) (src), \
strlen (src) + 1)) \
: __strcpy_g ((dest), (src))))

Try the test again with "#undef strcpy".

Oops; this was supposed to be a response to Seebs' reply about turning
strcpy() into memcpy().

But a similar point applies here: glibc's <bits/string.h> has:

#define strlen(str) \
(__extension__ (__builtin_constant_p (str) \
? __builtin_strlen (str) \
: __strlen_g (str)))

So I would expect "#undef strlen" to change this.
 
S

Seebs

But a similar point applies here: glibc's <bits/string.h> has:

#define strlen(str) \
(__extension__ (__builtin_constant_p (str) \
? __builtin_strlen (str) \
: __strlen_g (str)))

So I would expect "#undef strlen" to change this.

You might, but apparently some of this stuff is also hardwired in the compiler
in some cases. It may vary with architecture, though.

extern int strcpy(char *, char *);
int main(void) {
return 0;
}

gcc says:

t.c:1: warning: conflicting types for built-in function `strcpy'

So how about:

extern unsigned int strlen(const char *);
int main(void) {
return strlen("foo");
}

gcc produces:

main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $3, %eax
leave
ret

So, yes, it's gcc, not the headers.

craaaaazy stuff, huh.

-s
 
K

Kenny McCormack

Keith Thompson said:
Yes, *please*, do us all a favor and miss the fun.

Kiki still labors under two misconceptions:

1) That the words I type have magical properties, like Medusa's
head, such that mere exposure to them will cause horrific
results in the viewer. I know this sounds crazy on the surface,
but it is the only explanation I can find for why it is not
enough for him to simply not read these words (*), but rather he
must work extra hard to prevent others from reading them as well.

2) That he is the Supreme Executive Commander In Charge here, and
that nothing is allowed to escape his view and comment. Note,
in passing, that this fact (that Kiki will not allow any
item/thread in CLC to exist without at least one piece of input
from him) was used quite effectively by HfC, to prove that Kiki
was lying about his killfile usage. (**)

(*) Well, to be more accurate (and we know how highly accuracy is
prized in this newsgroup), to read and ignore them - but the effect
is the same. I.e., the effect is the same as if he never read them.

(**) This was one of many thoroughly effective such proofs. Do not
labor under the misconception that this was the only one.
 
N

Nobody

So how about:

extern unsigned int strlen(const char *);
int main(void) {
return strlen("foo");
}

Right; confirmed with gcc 4.3.4 on Linux/x86.

-fno-builtin disables this, as does -ffreestanding (older
versions of gcc have the former but not the latter).
 

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,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top