Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Re: endianness and failure with inline

Reply
Thread Tools

Re: endianness and failure with inline

 
 
Seebs
Guest
Posts: n/a
 
      10-15-2010
On 2010-10-15, doriangray <(E-Mail Removed)> wrote:
> Exactly. I thought that "inline" was just a hint to the compiler who
> is free to ignore hints, as it would with "register" variables.
> Why should we bother about something that the compiler is free to
> ignore? And also, isLE99() is only called in the same module where its
> defined, so I can't still understand what undefined reference means.


Okay, here's the thing.

isLE99() isn't static, so there's not a static definition of it.

It's declared inline, there's not an external definition of it.

There's a call to it. That call could EITHER be to the inline version
defined in this file, or to an external version defined in some other
file -- we don't know whether or not such an external version exists,
and indeed, an external one could be created long after this file has
been compiled! So the compiler has a free choice; it can either generate
a call to the externally-visible symbol (which could come from this file
or any other) or inline.

It chooses not to inline, but to generate a call. However, when we get to
linking, there's no external definition available, so the link fails with
an undefined reference.

We compiled something which was permitted to generate EITHER an inlined
version of the function OR a call to an external version of the function.

We compiled an inline version of the function, which could OPTIONALLY be
inlined, or could be ignored -- but which COULD NOT create an external
version of the function.

The compiler does not have the option of creating an external version
of the function, because it's declared inline without an extern modifier.
However, it does have the option of translating the call expression into
a call to the external identifier, on the grounds that you may well have
provided an external definition in another module.

Then, when linking comes around, we find that we have a call to a symbol
that no one ever defined. Whoops.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / http://www.velocityreviews.com/forums/(E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      10-15-2010
On 10/15/10 01:42 PM, Seebs wrote:
> On 2010-10-15, doriangray<(E-Mail Removed)> wrote:
>> Exactly. I thought that "inline" was just a hint to the compiler who
>> is free to ignore hints, as it would with "register" variables.
>> Why should we bother about something that the compiler is free to
>> ignore? And also, isLE99() is only called in the same module where its
>> defined, so I can't still understand what undefined reference means.

>
> Okay, here's the thing.
>
> isLE99() isn't static, so there's not a static definition of it.
>
> It's declared inline, there's not an external definition of it.
>
> There's a call to it. That call could EITHER be to the inline version
> defined in this file, or to an external version defined in some other
> file -- we don't know whether or not such an external version exists,
> and indeed, an external one could be created long after this file has
> been compiled! So the compiler has a free choice; it can either generate
> a call to the externally-visible symbol (which could come from this file
> or any other) or inline.
>
> It chooses not to inline, but to generate a call. However, when we get to
> linking, there's no external definition available, so the link fails with
> an undefined reference.
>
> We compiled something which was permitted to generate EITHER an inlined
> version of the function OR a call to an external version of the function.


I think your are probably correct here. But this is one case where the
correct behaviour is counter-intuitive.

Compiling with optimisation on does inline the function.

gcc 3.x makes the symbol global, Sun c99 make is local, which is what I
consider the "sensible" thing to do.

Causing a linkage failure depending on optimisation level isn't very
user friendly.

--
Ian Collins
 
Reply With Quote
 
 
 
 
Seebs
Guest
Posts: n/a
 
      10-15-2010
On 2010-10-15, Ian Collins <(E-Mail Removed)> wrote:
> I think your are probably correct here. But this is one case where the
> correct behaviour is counter-intuitive.


Yes, yes it is! It was sufficiently counterintuitive that I actually reported
it to the toolchain vendor at $dayjob to see whether they thought it was a
bug, but their explanation convinced me that, although I may think it's a
bug, if it is, it's a bug in the standard.

And thinking about it more, I don't think it's a bug in the standard; it's
just a limitation that comes about as a side-effect of the rule allowing
vendors to pick which of two versions of a function to use.

> Causing a linkage failure depending on optimisation level isn't very
> user friendly.


I'd agree. The problem is, I'm not sure I see a way to improve it without
breaking something.

The real-world usage case is that you might have a generic version of a
function which works in all sorts of cases, and then a local inline version
which can perform better in a specific case, but which you don't want to
use elsewhere.

According to several compiler vendors, people ACTUALLY DO THIS. They'll
do things like having an external rotate() which can rotate arbitrary
objects, and a local inline rotate() which works exceptionally fast, but
only on circles. And the thing is, it's very important for the performance
freaks to *permit* that. But it's not very helpful to vendors to *require*
that it work as-expected, because that implies making inlining work, and
you are NEVER required to actually successfully inline. So if your
compiler doesn't actually HAVE inlining as a possibility, it *MUST* generate
calls to the external symbol -- and because we just explicitly allowed
the inline function to have the same name as the external symbol, you can't
generate an external-linkage version of the function that the call can
get linked against.

So this really does seem to be a necessary side-effect, but I'm not
comfortable with using such a weak, mamby-pamby, word as "counterintuitive"
to describe it. The directly-downwind faster than the wind wind-powered
vehicle is "counterintuitive"*. This is much, much, more confusing.

-s[*] As in, most engineers will immediately tell you that it's obviously
impossible, and some will continue to insist this even after seeing it done,
though the majority seem to get it after a while. Although it's not
C-related, it is an awesome example of how cool physics gets around the
edges. See also fasterthanthewind.org.
--
Copyright 2010, all wrongs reversed. Peter Seebach / (E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
 
Reply With Quote
 
Seebs
Guest
Posts: n/a
 
      10-15-2010
On 2010-10-15, doriangray <(E-Mail Removed)> wrote:
> Thanks now it sounds much clearer, even if I'd prefer the compiler to
> treat it as static if it chooses not to make it inline.
> Would it sound more reasonable? Anyway, Thank you all.


That makes some sense to me, yes. I think there is probably a sound
reason for which it wasn't mandated, but it would certainly have surprised
me less.

Thanks a ton for the fascinating example/test case. Excellent question.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / (E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      10-15-2010
On 10/15/10 04:01 PM, Seebs wrote:
> On 2010-10-15, Ian Collins<(E-Mail Removed)> wrote:
>> I think your are probably correct here. But this is one case where the
>> correct behaviour is counter-intuitive.

>
> Yes, yes it is! It was sufficiently counterintuitive that I actually reported
> it to the toolchain vendor at $dayjob to see whether they thought it was a
> bug, but their explanation convinced me that, although I may think it's a
> bug, if it is, it's a bug in the standard.
>
> And thinking about it more, I don't think it's a bug in the standard; it's
> just a limitation that comes about as a side-effect of the rule allowing
> vendors to pick which of two versions of a function to use.
>
>> Causing a linkage failure depending on optimisation level isn't very
>> user friendly.

>
> I'd agree. The problem is, I'm not sure I see a way to improve it without
> breaking something.


It was an interesting discussion, just when I thought I knew all the
intricacies of inline, I found I didn't. I was assuming C and C++
followed the same rules (as some compilers appear to), but this is
another of those grey areas where the languages subtly differ.

> The real-world usage case is that you might have a generic version of a
> function which works in all sorts of cases, and then a local inline version
> which can perform better in a specific case, but which you don't want to
> use elsewhere.


<snip>

The C++ standard wording (7.1.2/4) forbids this, but provides extra
constraints and clarification:

"An inline function shall be defined in every translation unit in which
it is used and shall have exactly the same definition in every case"

Regarding linkage, it goes on to say:

"If a function with external linkage is declared inline in one
translation unit, it shall be declared inline in all translation units
in which it appears; no diagnostic is required. An inline function with
external linkage shall have the same address in all translation units."

and adds this which I don't think is mentioned in the C standard:

"A static local variable in an extern inline function always refers to
the same object. A string literal in an extern inline function is the
same object in different translation units."

> So this really does seem to be a necessary side-effect, but I'm not
> comfortable with using such a weak, mamby-pamby, word as "counterintuitive"
> to describe it.


A can't think of a better one I'd use in polite company!

> The directly-downwind faster than the wind wind-powered
> vehicle is "counterintuitive"*. This is much, much, more confusing.


Ah, you've been watching multi-hull yacht racing!

--
Ian Collins
 
Reply With Quote
 
Seebs
Guest
Posts: n/a
 
      10-15-2010
On 2010-10-15, Ian Collins <(E-Mail Removed)> wrote:
> On 10/15/10 04:01 PM, Seebs wrote:
>> The directly-downwind faster than the wind wind-powered
>> vehicle is "counterintuitive"*. This is much, much, more confusing.


> Ah, you've been watching multi-hull yacht racing!


Actually, no, it was a land-based cart. The official world record holder
in the newly-minted "directly down wind faster than the wind" category
for the land sail people. It did ~28mph in a 10mph wind, directly downwind,
powered only by the wind. Very impressive bit of work.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / (E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Multiple functions (one version being inline and other beingnon-inline) Rahul C++ 3 02-28-2008 03:28 PM
about extern inline and static inline Sean C++ 4 04-30-2006 03:18 PM
Endianness and streams kelvSYC C++ 8 06-06-2005 12:08 AM
endianness and sscanf/sprintf pramod C++ 22 01-06-2004 01:02 PM
endianness and sscanf/sprintf pramod C Programming 22 01-06-2004 01:02 PM



Advertisments