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

printf("%s\n", __FILE__); /* why SIGSEGV? */

P: n/a
why the following statement dumps the core(Segmentation fault)?

printf("%s\n", __FILE__);

May 29 '06 #1
Share this Question
Share on Google+
19 Replies


P: n/a
"v4vijayakumar" <v4***********@yahoo.com> writes:
why the following statement dumps the core(Segmentation fault)?

printf("%s\n", __FILE__);


Perhaps because it's not part of a complete C program. (If it were,
presumably you would have shown it to us.)

Or maybe the previous line defines printf as a macro.

Or maybe you closed stdout.

If you want actual answers rather than guesses, show us a complete
program. If this is a quiz rather than an actual problem you're
having, please say so.

--
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.
May 29 '06 #2

P: n/a

Keith Thompson wrote:
"v4vijayakumar" <v4***********@yahoo.com> writes:
why the following statement dumps the core(Segmentation fault)?

printf("%s\n", __FILE__);


Perhaps because it's not part of a complete C program. (If it were,
presumably you would have shown it to us.)

Or maybe the previous line defines printf as a macro.

Or maybe you closed stdout.

If you want actual answers rather than guesses, show us a complete
program. If this is a quiz rather than an actual problem you're
having, please say so.

--
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.


sorry. Here is the complete program and sample run.

#cat test.c
#include <stdio.h>

int main()
{
printf("%s\n", __FILE__);
printf("%s\n", __LINE__);
printf("%s\n", __func__);

return 0;
}

#cc test.c
#./a.out
test.c
Segmentation fault (core dumped)
#

May 29 '06 #3

P: n/a
Keith Thompson <ks***@mib.org> wrote:
"v4vijayakumar" <v4***********@yahoo.com> writes:
why the following statement dumps the core(Segmentation fault)?

printf("%s\n", __FILE__);
Perhaps because it's not part of a complete C program. (If it were,
presumably you would have shown it to us.)


[...]

Must likely the next statement is something like

printf("%s\n",__LINE__);

;-)
May 29 '06 #4

P: n/a
v4vijayakumar wrote:
Keith Thompson wrote:
"v4vijayakumar" <v4***********@yahoo.com> writes:
why the following statement dumps the core(Segmentation fault)?

printf("%s\n", __FILE__);
Perhaps because it's not part of a complete C program. (If it were,
presumably you would have shown it to us.)

Or maybe the previous line defines printf as a macro.

Or maybe you closed stdout.

If you want actual answers rather than guesses, show us a complete
program. If this is a quiz rather than an actual problem you're
having, please say so.

--
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.


sorry. Here is the complete program and sample run.

#cat test.c
#include <stdio.h>

int main()


Use int main(void)
{
printf("%s\n", __FILE__);
printf("%s\n", __LINE__);


__LINE__ expands to a decimal integer constant. But you've supplied a
conversion character that expects a pointer to a char. Use:

printf("%d\n", __LINE__);

May 29 '06 #5

P: n/a
"v4vijayakumar" <v4***********@yahoo.com> wrote in message
news:11**********************@j55g2000cwa.googlegr oups.com...

sorry. Here is the complete program and sample run.

#cat test.c
#include <stdio.h>

int main()
{
printf("%s\n", __FILE__);
printf("%s\n", __LINE__);
printf("%s\n", __func__);

return 0;
}

#cc test.c
#./a.out
test.c
Segmentation fault (core dumped)
#
My system doesn't define __func__, so I took that line out. Running that, I
get a segfault just like you. However, a couple seconds of looking tells me
the problem:
gcc -E test.c |tail

int main()
{
printf("%s\n", "test.c");
printf("%s\n", 6);

return 0;
}

__LINE__ is replaced with 6, not "6", so %s is not the correct format
specifier. Using %d works just fine.

I'm sure someone will comment on whether this is required or up to the
implementation.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin
*** Posted via a free Usenet account from http://www.teranews.com ***
May 29 '06 #6

P: n/a
pc

v4vijayakumar wrote:
Keith Thompson wrote:
"v4vijayakumar" <v4***********@yahoo.com> writes:
why the following statement dumps the core(Segmentation fault)?

printf("%s\n", __FILE__);


Perhaps because it's not part of a complete C program. (If it were,
presumably you would have shown it to us.)

Or maybe the previous line defines printf as a macro.

Or maybe you closed stdout.

If you want actual answers rather than guesses, show us a complete
program. If this is a quiz rather than an actual problem you're
having, please say so.

--
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.


sorry. Here is the complete program and sample run.

#cat test.c
#include <stdio.h>

int main()
{
printf("%s\n", __FILE__);
printf("%s\n", __LINE__);
printf("%s\n", __func__);

return 0;
}


perhaps you wanted this
int main()
{
printf("%s\n", __FILE__);
printf("%d\n", __LINE__); <<<< note the change
printf("%s\n", __func__);
return 0;
}

May 29 '06 #7

P: n/a
Stephen Sprunk wrote:
"v4vijayakumar" <v4***********@yahoo.com> wrote in message
news:11**********************@j55g2000cwa.googlegr oups.com...

sorry. Here is the complete program and sample run.

#cat test.c
#include <stdio.h>

int main()
{
printf("%s\n", __FILE__);
printf("%s\n", __LINE__);
printf("%s\n", __func__);

return 0;
}

#cc test.c
#./a.out
test.c
Segmentation fault (core dumped)
#


My system doesn't define __func__, so I took that line out. Running that, I
get a segfault just like you. However, a couple seconds of looking tells me
the problem:
gcc -E test.c |tail

int main()
{
printf("%s\n", "test.c");
printf("%s\n", 6);

return 0;
}

__LINE__ is replaced with 6, not "6", so %s is not the correct format
specifier. Using %d works just fine.

I'm sure someone will comment on whether this is required or up to the
implementation.


Keith will provide the last word but as far as can tell from my library
refernce, __LINE__ expands to a decimal integer constant. So yes, %d is
needed and %s is the wrong conversion specifier to use.

Additionally, the OP implementation may not be fully C99 compliant in
which case the last of his printf's may also be the cause of the
segmentation fault.

May 29 '06 #8

P: n/a
"v4vijayakumar" <v4***********@yahoo.com> wrote:
why the following statement dumps the core(Segmentation fault)?

printf("%s\n", __FILE__);


Because you have made a mistake earlier in the code, probably involving
writing through an invalid pointer. That line in itself is fine.

Richard
May 29 '06 #9

P: n/a
"santosh" <sa*********@gmail.com> writes:
Stephen Sprunk wrote:
"v4vijayakumar" <v4***********@yahoo.com> wrote in message
news:11**********************@j55g2000cwa.googlegr oups.com...
>
> sorry. Here is the complete program and sample run.
>
> #cat test.c
> #include <stdio.h>
>
> int main()
> {
> printf("%s\n", __FILE__);
> printf("%s\n", __LINE__);
> printf("%s\n", __func__);
>
> return 0;
> }
[snip] __LINE__ is replaced with 6, not "6", so %s is not the correct format
specifier. Using %d works just fine.

I'm sure someone will comment on whether this is required or up to the
implementation.


Keith will provide the last word but as far as can tell from my library
refernce, __LINE__ expands to a decimal integer constant. So yes, %d is
needed and %s is the wrong conversion specifier to use.

Additionally, the OP implementation may not be fully C99 compliant in
which case the last of his printf's may also be the cause of the
segmentation fault.


C99 6.10.8:

__FILE__ The presumed name of the current source file (a
character string literal).

__LINE__ The presumed line number (within the current source
file) of the current source line (an integer
constant).

with a footnote:

The presumed source file name and line number can be changed by
the #line directive.

The wording in C90 is a bit different:

__LINE__ The line number of the current source line (a decimal
constant).

__FILE__ The presumed name of the source file (a character string
literal).

A couple of odd points: C99 dropped the requirement that __LINE__ has
to be a *decimal* constant. And neither standard requires the
expansion of __LINE__ to be of type int. Possibly that's meant to
cater to implementations with 16-bit int that allow source files
longer than 32767 lines.

It looks like, strictly speaking, this:
printf("%d\n", __LINE__);
could invoke undefined behavior; to avoid the problem, use this:
printf("%d\n", (int)__LINE__);
or this:
printf("%ld\n", (long)__LINE__);

--
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.
May 29 '06 #10

P: n/a
Keith Thompson wrote:
"santosh" <sa*********@gmail.com> writes:
Keith will provide the last word but as far as can tell from my library
refernce, __LINE__ expands to a decimal integer constant. So yes, %d is
needed and %s is the wrong conversion specifier to use.
.... snip ...
A couple of odd points: C99 dropped the requirement that __LINE__ has
to be a *decimal* constant. And neither standard requires the
expansion of __LINE__ to be of type int. Possibly that's meant to
cater to implementations with 16-bit int that allow source files
longer than 32767 lines.

It looks like, strictly speaking, this:
printf("%d\n", __LINE__);
could invoke undefined behavior; to avoid the problem, use this:
printf("%d\n", (int)__LINE__);
or this:
printf("%ld\n", (long)__LINE__);


Or:
printf("%lu\n", (unsigned long) __LINE__);

May 29 '06 #11

P: n/a
2006-05-29 <11**********************@j55g2000cwa.googlegroups .com>, v4vijayakumar wrote:

Keith Thompson wrote:
"v4vijayakumar" <v4***********@yahoo.com> writes:
> why the following statement dumps the core(Segmentation fault)?
>
> printf("%s\n", __FILE__);


Perhaps because it's not part of a complete C program. (If it were,
presumably you would have shown it to us.)

Or maybe the previous line defines printf as a macro.

Or maybe you closed stdout.

If you want actual answers rather than guesses, show us a complete
program. If this is a quiz rather than an actual problem you're
having, please say so.

--
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.


sorry. Here is the complete program and sample run.

#cat test.c
#include <stdio.h>

int main()
{
printf("%s\n", __FILE__);
printf("%s\n", __LINE__);
printf("%s\n", __func__);

return 0;
}

#cc test.c
#./a.out
test.c
Segmentation fault (core dumped)
#


printf("%s\n",__LINE__) is causing the segfault. if it were the __FILE__
line causing the segfault, you likely wouldn't see its output.
May 29 '06 #12

P: n/a
2006-05-29 <11**********************@y43g2000cwc.googlegroups .com>, santosh wrote:
Keith Thompson wrote:
"santosh" <sa*********@gmail.com> writes:
> Keith will provide the last word but as far as can tell from my library
> refernce, __LINE__ expands to a decimal integer constant. So yes, %d is
> needed and %s is the wrong conversion specifier to use.

... snip ...
A couple of odd points: C99 dropped the requirement that __LINE__ has
to be a *decimal* constant. And neither standard requires the
expansion of __LINE__ to be of type int. Possibly that's meant to
cater to implementations with 16-bit int that allow source files
longer than 32767 lines.

It looks like, strictly speaking, this:
printf("%d\n", __LINE__);
could invoke undefined behavior; to avoid the problem, use this:
printf("%d\n", (int)__LINE__);
or this:
printf("%ld\n", (long)__LINE__);


Or:
printf("%lu\n", (unsigned long) __LINE__);


or
#define s(x) #x

printf("%s\n", s(__LINE__));

or even

printf(""s(__LINE__)"\n");
May 29 '06 #13

P: n/a
Jordan Abel schrieb:

or
#define s(x) #x

printf("%s\n", s(__LINE__));

or even

printf(""s(__LINE__)"\n");


This prints "__LINE__" for me. ITYM something like

#define xs(x) #x
#define s(x) xs(x)

printf("%s\n",s(__LINE__));

printf(s(__LINE__)"\n");

This extra level is needed as otherwise __LINE__ will not be evaluated
before it is stringized resulting in "__LINE__".

--
Marc Thrun
http://www.tekwarrior.de/
May 29 '06 #14

P: n/a
"santosh" <sa*********@gmail.com> writes:
Keith Thompson wrote:
"santosh" <sa*********@gmail.com> writes:
> Keith will provide the last word but as far as can tell from my library
> refernce, __LINE__ expands to a decimal integer constant. So yes, %d is
> needed and %s is the wrong conversion specifier to use.

... snip ...
A couple of odd points: C99 dropped the requirement that __LINE__ has
to be a *decimal* constant. And neither standard requires the
expansion of __LINE__ to be of type int. Possibly that's meant to
cater to implementations with 16-bit int that allow source files
longer than 32767 lines.

It looks like, strictly speaking, this:
printf("%d\n", __LINE__);
could invoke undefined behavior; to avoid the problem, use this:
printf("%d\n", (int)__LINE__);
or this:
printf("%ld\n", (long)__LINE__);


Or:
printf("%lu\n", (unsigned long) __LINE__);


Yes, that's an important improvement if the printf statement appears
on line 2147483648 or later of the source file. 8-)}

--
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.
May 29 '06 #15

P: n/a
Keith Thompson wrote:
A couple of odd points: C99 dropped the requirement that __LINE__ has
to be a *decimal* constant. And neither standard requires the
expansion of __LINE__ to be of type int. Possibly that's meant to
cater to implementations with 16-bit int that allow source files
longer than 32767 lines.

It looks like, strictly speaking, this:
printf("%d\n", __LINE__);
could invoke undefined behavior; to avoid the problem, use this:
printf("%d\n", (int)__LINE__);
or this:
printf("%ld\n", (long)__LINE__);


I don't understand that last point. I tought that parameters passed to
printf that matched a %d conversion in a printf call were implicitly
converted to int, isn't it?

I mean, if you have the following snippet (take all needed headers as
included):

unsigned short int a = 5;
printf("%d\n", a);

printf function doesn't receive an 'int' argument (by making an implicit
conversion to 'a')? Or I'm totally wrong?

--
Luis Alberto Giménez
JabberID: Si*******@bulmalug.net
GnuPG ID: 0x3BAABDE1
May 30 '06 #16

P: n/a
In article <f1************@bart.mydomain.com>,
=?ISO-8859-1?Q?Alberto_Gim=E9nez?= <al***************@teleline.es> wrote:
I tought that parameters passed to
printf that matched a %d conversion in a printf call were implicitly
converted to int, isn't it?
No. Parameter values *never* have their type converted based upon
the format string: instead it is your responsibility to ensure that
the format string matches the parameter value's type.

I mean, if you have the following snippet (take all needed headers as
included): unsigned short int a = 5;
printf("%d\n", a); printf function doesn't receive an 'int' argument (by making an implicit
conversion to 'a')? Or I'm totally wrong?


The unsigned short will undergo "the usual conversions" to
unsigned int just because it appears in a function call in a position
prototyped as ... (three periods). %d is the wrong format string
to print out an unsigned int. You just didn't happen to notice it
because the value wasn't greater than the maximum signed positive
integer.
--
"It is important to remember that when it comes to law, computers
never make copies, only human beings make copies. Computers are given
commands, not permission. Only people can be given permission."
-- Brad Templeton
May 30 '06 #17

P: n/a


Alberto Giménez wrote On 05/30/06 12:55,:
Keith Thompson wrote:
A couple of odd points: C99 dropped the requirement that __LINE__ has
to be a *decimal* constant. And neither standard requires the
expansion of __LINE__ to be of type int. Possibly that's meant to
cater to implementations with 16-bit int that allow source files
longer than 32767 lines.

It looks like, strictly speaking, this:
printf("%d\n", __LINE__);
could invoke undefined behavior; to avoid the problem, use this:
printf("%d\n", (int)__LINE__);
or this:
printf("%ld\n", (long)__LINE__);



I don't understand that last point. I tought that parameters passed to
printf that matched a %d conversion in a printf call were implicitly
converted to int, isn't it?

I mean, if you have the following snippet (take all needed headers as
included):

unsigned short int a = 5;
printf("%d\n", a);

printf function doesn't receive an 'int' argument (by making an implicit
conversion to 'a')? Or I'm totally wrong?


You are not toally wrong, but not totally right.

First, the "default argument promotions" do not depend
on the conversion specifiers found in the printf() format
string. The same promotions are used for all arguments that
match the "..." part of a variadic function's parameter list,
and to all arguments that are passed to functions declared
without prototypes. These promotions are:

1: All "small integer" types (char, short, bit-fields,
enums, ...) are promoted to `int' or to `unsigned int'.
The promtion is to `int' if the `int' type can hold
all possible values of the original type, or to
`unsigned int' otherwise.

2: `float' values are promoted to `double'.

3: All other argument types are passed unchanged.

With these rules in mind, we can now address the issues
you and Keith Thompson have raised.

Keith points out that __LINE__ might produce a constant
whose type is not `int'. For example, it might produce an
`unsigned int' or a `long' or even something more exotic
(the C99 Standard vastly expanded the possible repertoire
of integer types). You know that "%d" requires a matching
`int', but you don't know what __LINE__ produces nor what
it will be promoted to. Keith suggests using a cast to
convert the value of __LINE__ to a `long', and then (now
that you're sure of what dealing with) using "%ld" to
print it.

You raise the issue of what happens when an `unsigned
short' is passed to printf(). This turns out to be a wee
bit tricky, because Rule 1 has two possible outcomes:

1a: If `int' can represent all the possible values an
`unsigned short' might have, `unsigned short'
promotes to `int'.

1b: If there are some `unsigned short' values that are
not representable as `int', `unsigned short' promotes
to `unsigned int'.

The problem is that the C Standard allows the implementation
a lot of leeway in choosing the sizes of its data types, and
different choices lead to different results. On a machine
with (say) 32-bit `int' and 16-bit `unsigned short', Rule 1a
will apply and the promotion will be to `int'. But on a
machine where both `int' and `unsigned short' have 16 bits,
Rule 1b will apply and the promotion will give `unsigned int'.
Therefore, the conversion specifier for `unsigned short' (as
promoted) should be "%d" on some systems, "%u" on others.

The Standard says that using "%d" with `unsigned int'
or "%u" with `int' amounts to a mismatch between the format
string and the argument, and thus yields undefined behavior.
As a practical matter, discrepancies of signedness hardly if
ever make any difference (mismatches of width are another
matter, of course). This is in part because the people who
make C implementations have little incentive to make things
difficult gratuitously; if anything, they find that their C
implementations will be more popular if they are "friendly"
and let the programmer skirt the law in small ways. Still,
for 100% belt-AND-suspenders never-drive-over-55 safety, you
should print an `unsigned short' value with something like

printf ("%u\n", (unsigned int)ushort_value);

... so you're not subject to the implementation's whims
about whether to apply Rule 1a or 1b.

--
Er*********@sun.com

May 30 '06 #18

P: n/a
Alberto Giménez wrote:
Keith Thompson wrote:
A couple of odd points: C99 dropped the requirement that __LINE__ has
to be a *decimal* constant. And neither standard requires the
expansion of __LINE__ to be of type int. Possibly that's meant to ^^^^^^^^^^^^^^^^^^^^^^^^ cater to implementations with 16-bit int that allow source files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ longer than 32767 lines. ^^^^^^^^^^^^^^^^^^^^^^^
It looks like, strictly speaking, this:
printf("%d\n", __LINE__);
could invoke undefined behavior; to avoid the problem, use this:
printf("%d\n", (int)__LINE__);
or this:
printf("%ld\n", (long)__LINE__);

I don't understand that last point. I tought that parameters passed to
printf that matched a %d conversion in a printf call were implicitly
converted to int, isn't it?


I doubt that long will ever be implicitly promoted to int, nor will
unsigned long. So as Keith was suggesting if the line number is larger
than 32767 it could be either unsigned in (which won't promote to int),
long, unsigned long or even on C99 unsigned long long. If this is a
concern then:
printf("%lu\n", (unsigned long)__LINE__);
for C89 or
printf("%llu\n", (unsigned long long)__LINE__);
would be better if you want to cope with stupidly long source files. Of
course, I would wonder about source files longer than 32767 lines
anyway, so for any sensible program Keith's suggestion should be fine.
I mean, if you have the following snippet (take all needed headers as
included):

unsigned short int a = 5;
printf("%d\n", a);

printf function doesn't receive an 'int' argument (by making an implicit
conversion to 'a')? Or I'm totally wrong?


You are partially wrong. It could be promoted to unsigned int. This is
especially likely when programming for DSPs where it is common to have
char, short and int as the same size, with CHAR_BIT being large enough
for this to be legal (e.g. you have 16 bit char, short and int on the C
compiler for the TMS320C25).
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
May 30 '06 #19

P: n/a
On Tue, 30 May 2006 17:16:37 +0000 (UTC), ro******@ibd.nrc-cnrc.gc.ca
(Walter Roberson) wrote:
In article <f1************@bart.mydomain.com>,
=?ISO-8859-1?Q?Alberto_Gim=E9nez?= <al***************@teleline.es> wrote:
I tought that parameters passed to
printf that matched a %d conversion in a printf call were implicitly
converted to int, isn't it?
No. Parameter values *never* have their type converted based upon
the format string: instead it is your responsibility to ensure that
the format string matches the parameter value's type.

But they are promoted by standard rules; actually you must ensure that
the format string matches the _promoted_ types. Or vice versa.
I mean, if you have the following snippet (take all needed headers as
included):
unsigned short int a = 5;
printf("%d\n", a);

printf function doesn't receive an 'int' argument (by making an implicit
conversion to 'a')? Or I'm totally wrong?


The unsigned short will undergo "the usual conversions" to
unsigned int just because it appears in a function call in a position


There are actually three different but closely related concepts:

- the "integer promotions" take integer types of lower rank than int
(and bitfields) to either signed int if it can represent the entire
range of value and otherwise to unsigned int. On many S16I32 systems
unsigned short goes to signed int. These apply to nearly all
computational operators.

- the "default argument promotions" are used for varargs (prototyped
as you say with ellipsis) and for unprototyped aka K&R1 functions;
these apply the integer promotions and also do float->double.

- the "usual arithmetic conversions" are used for most binary
(2-operand) operators, with some exceptions like shift, plus the
ternary conditional operator. They apply the integer promotions to
both operands and then convert both to a common type that is chosen by
rules that boil down to the 'least' type that 'covers' both. This is
sometimes called 'contagion', e.g. 1 + 3.0 is done in (the int 1 is
converted to) floating point, namely double; c + 3.0f where c is
complex is done in (the real float is converted to) complex, etc.
prototyped as ... (three periods). %d is the wrong format string
to print out an unsigned int. You just didn't happen to notice it
because the value wasn't greater than the maximum signed positive
integer.


If it is indeed promoted to unsigned int, yes %d is technically wrong,
but in practice will work if the value is in range as you note.

- David.Thompson1 at worldnet.att.net
Jun 8 '06 #20

This discussion thread is closed

Replies have been disabled for this discussion.