Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #145732 > unrolled thread

Question about use (and non-use) of "extern"

Started bygazelle@shell.xmission.com (Kenny McCormack)
First post2019-08-20 13:11 +0000
Last post2019-09-06 20:24 +0200
Articles 20 on this page of 42 — 15 participants

Back to article view | Back to comp.lang.c


Contents

  Question about use (and non-use) of "extern" gazelle@shell.xmission.com (Kenny McCormack) - 2019-08-20 13:11 +0000
    Re: Question about use (and non-use) of "extern" David Brown <david.brown@hesbynett.no> - 2019-08-20 16:09 +0200
    Re: Question about use (and non-use) of "extern" Bart <bc@freeuk.com> - 2019-08-20 16:41 +0100
      Re: Question about use (and non-use) of "extern" Bart <bc@freeuk.com> - 2019-08-20 16:47 +0100
      Re: Question about use (and non-use) of "extern" David Brown <david.brown@hesbynett.no> - 2019-08-20 19:27 +0200
        Re: Question about use (and non-use) of "extern" Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2019-08-20 13:54 -0400
          Re: Question about use (and non-use) of "extern" Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-08-21 02:09 +0100
          Re: Question about use (and non-use) of "extern" David Brown <david.brown@hesbynett.no> - 2019-08-21 10:54 +0200
        Re: Question about use (and non-use) of "extern" Bart <bc@freeuk.com> - 2019-08-21 00:41 +0100
          Re: Question about use (and non-use) of "extern" David Brown <david.brown@hesbynett.no> - 2019-08-21 10:58 +0200
    Re: Question about use (and non-use) of "extern" richard@cogsci.ed.ac.uk (Richard Tobin) - 2019-08-20 16:10 +0000
      Re: Question about use (and non-use) of "extern" Siri Cruise <chine.bleu@yahoo.com> - 2019-08-20 16:23 -0700
    Re: Question about use (and non-use) of "extern" already5chosen@yahoo.com - 2019-08-21 06:50 -0700
      Re: Question about use (and non-use) of "extern" gazelle@shell.xmission.com (Kenny McCormack) - 2019-08-22 20:20 +0000
        Re: Question about use (and non-use) of "extern" David Brown <david.brown@hesbynett.no> - 2019-08-23 00:25 +0200
        Re: Question about use (and non-use) of "extern" Bart <bc@freeuk.com> - 2019-08-23 01:35 +0100
          Re: Question about use (and non-use) of "extern" gazelle@shell.xmission.com (Kenny McCormack) - 2019-08-23 03:40 +0000
            Re: Question about use (and non-use) of "extern" Bart <bc@freeuk.com> - 2019-08-23 11:09 +0100
          Re: Question about use (and non-use) of "extern" David Brown <david.brown@hesbynett.no> - 2019-08-23 08:16 +0200
        Re: Question about use (and non-use) of "extern" scott@slp53.sl.home (Scott Lurndal) - 2019-08-23 15:02 +0000
          Re: Question about use (and non-use) of "extern" Bart <bc@freeuk.com> - 2019-08-23 17:06 +0100
            Re: Question about use (and non-use) of "extern" gazelle@shell.xmission.com (Kenny McCormack) - 2019-08-23 18:40 +0000
            Re: Question about use (and non-use) of "extern" scott@slp53.sl.home (Scott Lurndal) - 2019-08-23 20:38 +0000
              Re: Question about use (and non-use) of "extern" Richard Damon <Richard@Damon-Family.org> - 2019-08-23 17:55 -0400
                Richard Damon weighs in... (Was: Question about use (and non-use) of "extern") gazelle@shell.xmission.com (Kenny McCormack) - 2019-08-23 23:50 +0000
    Re: Question about use (and non-use) of "extern" Andrey Tarasevich <andreytarasevich@hotmail.com> - 2019-08-27 15:03 -0700
      Re: Question about use (and non-use) of "extern" Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-09-03 05:57 -0700
        Re: Question about use (and non-use) of "extern" David Brown <david.brown@hesbynett.no> - 2019-09-03 15:45 +0200
          Re: Question about use (and non-use) of "extern" Keith Thompson <kst-u@mib.org> - 2019-09-03 11:13 -0700
            Re: Question about use (and non-use) of "extern" David Brown <david.brown@hesbynett.no> - 2019-09-04 12:11 +0200
              Re: Question about use (and non-use) of "extern" James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-09-04 08:18 -0400
            Re: Question about use (and non-use) of "extern" Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-09-06 02:25 -0700
              Re: Question about use (and non-use) of "extern" David Brown <david.brown@hesbynett.no> - 2019-09-06 11:45 +0200
            Re: Question about use (and non-use) of "extern" Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-09-06 21:15 +0100
          Re: Question about use (and non-use) of "extern" James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-09-03 21:10 -0400
            Re: Question about use (and non-use) of "extern" David Brown <david.brown@hesbynett.no> - 2019-09-04 12:21 +0200
        Re: Question about use (and non-use) of "extern" Andrey Tarasevich <andreytarasevich@hotmail.com> - 2019-09-04 12:04 -0700
          Re: Question about use (and non-use) of "extern" James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-09-04 15:29 -0400
          Re: Question about use (and non-use) of "extern" Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-09-06 02:46 -0700
    Re: Question about use (and non-use) of "extern" Bonita Montero <Bonita.Montero@gmail.com> - 2019-09-05 10:01 +0200
      Re: Question about use (and non-use) of "extern" Andrey Tarasevich <andreytarasevich@hotmail.com> - 2019-09-05 10:43 -0700
        Re: Question about use (and non-use) of "extern" Bonita Montero <Bonita.Montero@gmail.com> - 2019-09-06 20:24 +0200

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#145764

FromBart <bc@freeuk.com>
Date2019-08-23 17:06 +0100
Message-ID<2aU7F.241504$xm3.80035@fx15.am4>
In reply to#145763
On 23/08/2019 16:02, Scott Lurndal wrote:
> gazelle@shell.xmission.com (Kenny McCormack) writes:
>> In article <53bbfbee-9a43-4980-b800-0667d8f3497a@googlegroups.com>,
>> <already5chosen@yahoo.com> wrote:
>> ...
>>>> 2) If you "extern" it nowhere, it works fine.
>>>
>>> That's non-standard, but in accordance with ancient UNIX tradition.
>>> Try to not rely on it if you care about non-UNIX.
>>
>> I don't.
>>
>> Here's what I get from the responses so far:
>>
>> If you filter out all the usual Usenet noise, it boils down to "It's not
>> "standard", but it works on Unix".  I'm fine with that.
>>
>> Now, here where it gets interesting.  I'm writing a shared library.  The
>> routines in the shared library need to share access to a global variable
>> ("int i" in the above examples).  So, I do "int i" at file level and it all
>> works fine.  Now, the thing is, the host program (the program that loads
>> the library) may or may not have declared its own "int i".  If it has, I
>> want to use it (the host program's variable), rather than my own.  (If it
>> doesn't, then of course I need to use my own...)
>>
> 
> Declare the 'i' in the library as 'weak'.
> 
> int i __attribute__((weak));
> 

AIUI, this defines this 'i' provided no non-weak 'i' exists anywhere 
else in the global set of symbols for this program unit (executable or 
shared library).

But when building the shared library, the host program that uses the 
shared library will be known, so the library's 'i' will always be used.

It might work if the library called is statically linked from object 
code, not dynamically.

[toc] | [prev] | [next] | [standalone]


#145766

Fromgazelle@shell.xmission.com (Kenny McCormack)
Date2019-08-23 18:40 +0000
Message-ID<qjpbug$brq$1@news.xmission.com>
In reply to#145764
In article <2aU7F.241504$xm3.80035@fx15.am4>, Bart  <bc@freeuk.com> wrote:
...
(Somebody else suggested)
>> Declare the 'i' in the library as 'weak'.
>> 
>> int i __attribute__((weak));
>> 
>
>AIUI, this defines this 'i' provided no non-weak 'i' exists anywhere 
>else in the global set of symbols for this program unit (executable or 
>shared library).
>
>But when building the shared library, the host program that uses the 
>shared library will be known, so the library's 'i' will always be used.
>
>It might work if the library called is statically linked from object 
>code, not dynamically.

Correct. Suggestion is no good.  As Bart surmises, it may work within a
single linking session, but not across separate links (and by "link", I
mean executions of the program "ld").

There is a solution, however.  See code below:

--- Cut here ---
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <assert.h>

#ifdef SHARED
/* Compile: gcc -DSHARED -fPIC -s -shared -W -Wall -Werror -o TestCoalesce.so TestCoalesce.c */
int *p_i;
void TestIt(void)
{
    void *getsym = dlsym(NULL,"host_p_i");

    /* See the value change from 12 to 17, and then stay 17 in the host */
    printf("getsym = %p\n",getsym);
    if (getsym)
	printf("In TestIt(), i = %d\n",*(p_i = * (int **) getsym));
    else p_i = malloc(sizeof(int));
    printf("Value of i (%p) in TestIt(): %d\n",p_i,*p_i = 17);
}
#else
/* Compile: gcc -rdynamic [-DDEFINE_I] -s -W -Wall -Werror -o TestCoalesce TestCoalesce.c -ldl */

#ifdef DEFINE_I
int i = 12, *host_p_i = &i;
#endif

int main(void)
{
    void *handle;
    void (*the_fun)();

#ifdef DEFINE_I
    printf("Original value of host_p_i (%p) in main(): %d\n",host_p_i,*host_p_i);
#endif
    assert((handle = dlopen("./TestCoalesce.so",RTLD_NOW)));
    assert((the_fun = dlsym(handle,"TestIt")));
    the_fun();
#ifdef DEFINE_I
    printf("Final value of i in main(): %d\n",i);
#endif
}
#endif
--- Cut here ---

-- 
The randomly chosen signature file that would have appeared here is more than 4
lines long.  As such, it violates one or more Usenet RFCs.  In order to remain
in compliance with said RFCs, the actual sig can be found at the following URL:
	http://user.xmission.com/~gazelle/Sigs/Seneca

[toc] | [prev] | [next] | [standalone]


#145768

Fromscott@slp53.sl.home (Scott Lurndal)
Date2019-08-23 20:38 +0000
Message-ID<m9Y7F.82918$9i3.14478@fx42.iad>
In reply to#145764
Bart <bc@freeuk.com> writes:
>On 23/08/2019 16:02, Scott Lurndal wrote:
>> gazelle@shell.xmission.com (Kenny McCormack) writes:
>>> In article <53bbfbee-9a43-4980-b800-0667d8f3497a@googlegroups.com>,
>>> <already5chosen@yahoo.com> wrote:
>>> ...
>>>>> 2) If you "extern" it nowhere, it works fine.
>>>>
>>>> That's non-standard, but in accordance with ancient UNIX tradition.
>>>> Try to not rely on it if you care about non-UNIX.
>>>
>>> I don't.
>>>
>>> Here's what I get from the responses so far:
>>>
>>> If you filter out all the usual Usenet noise, it boils down to "It's not
>>> "standard", but it works on Unix".  I'm fine with that.
>>>
>>> Now, here where it gets interesting.  I'm writing a shared library.  The
>>> routines in the shared library need to share access to a global variable
>>> ("int i" in the above examples).  So, I do "int i" at file level and it all
>>> works fine.  Now, the thing is, the host program (the program that loads
>>> the library) may or may not have declared its own "int i".  If it has, I
>>> want to use it (the host program's variable), rather than my own.  (If it
>>> doesn't, then of course I need to use my own...)
>>>
>> 
>> Declare the 'i' in the library as 'weak'.
>> 
>> int i __attribute__((weak));
>> 
>
>AIUI, this defines this 'i' provided no non-weak 'i' exists anywhere 
>else in the global set of symbols for this program unit (executable or 
>shared library).

It marks the symbol in that library as weak.

When the library is loaded(dynamically linked) at runtime, and the host program (for
which the shared object is a dependency) version (if it exists) will
be used.   Otherwise the library version will be used.

>
>But when building the shared library, the host program that uses the 
>shared library will be known, so the library's 'i' will always be used.

No.  When you build a shared library, you have no idea what executable
will link with that library at runtime.

The weak symbols are there specifically to provide the semantics desired
by the O.P.

Note that unix and unix-like systems typically defined most library symbols as weak
so they can be overridden by the application if required.

[toc] | [prev] | [next] | [standalone]


#145769

FromRichard Damon <Richard@Damon-Family.org>
Date2019-08-23 17:55 -0400
Message-ID<YgZ7F.223119$gM.160082@fx19.iad>
In reply to#145768
On 8/23/19 4:38 PM, Scott Lurndal wrote:
> Bart <bc@freeuk.com> writes:
>> On 23/08/2019 16:02, Scott Lurndal wrote:
>>> gazelle@shell.xmission.com (Kenny McCormack) writes:
>>>> In article <53bbfbee-9a43-4980-b800-0667d8f3497a@googlegroups.com>,
>>>> <already5chosen@yahoo.com> wrote:
>>>> ...
>>>>>> 2) If you "extern" it nowhere, it works fine.
>>>>>
>>>>> That's non-standard, but in accordance with ancient UNIX tradition.
>>>>> Try to not rely on it if you care about non-UNIX.
>>>>
>>>> I don't.
>>>>
>>>> Here's what I get from the responses so far:
>>>>
>>>> If you filter out all the usual Usenet noise, it boils down to "It's not
>>>> "standard", but it works on Unix".  I'm fine with that.
>>>>
>>>> Now, here where it gets interesting.  I'm writing a shared library.  The
>>>> routines in the shared library need to share access to a global variable
>>>> ("int i" in the above examples).  So, I do "int i" at file level and it all
>>>> works fine.  Now, the thing is, the host program (the program that loads
>>>> the library) may or may not have declared its own "int i".  If it has, I
>>>> want to use it (the host program's variable), rather than my own.  (If it
>>>> doesn't, then of course I need to use my own...)
>>>>
>>>
>>> Declare the 'i' in the library as 'weak'.
>>>
>>> int i __attribute__((weak));
>>>
>>
>> AIUI, this defines this 'i' provided no non-weak 'i' exists anywhere 
>> else in the global set of symbols for this program unit (executable or 
>> shared library).
> 
> It marks the symbol in that library as weak.
> 
> When the library is loaded(dynamically linked) at runtime, and the host program (for
> which the shared object is a dependency) version (if it exists) will
> be used.   Otherwise the library version will be used.
> 
>>
>> But when building the shared library, the host program that uses the 
>> shared library will be known, so the library's 'i' will always be used.
> 
> No.  When you build a shared library, you have no idea what executable
> will link with that library at runtime.
> 
> The weak symbols are there specifically to provide the semantics desired
> by the O.P.
> 
> Note that unix and unix-like systems typically defined most library symbols as weak
> so they can be overridden by the application if required.
> 

My understanding is that the __attribute__((weak)) applies at the time
of (static) linking, not loading, thus does not affect the dynamic
loading of a library.

One BIG problem with his idea is a SHARED library doesn't have A calling
program, but at any given time might have 0, 1, or 2 or more programs
(dynamically) linked to it, so the library can't have linking options
based on the calling program (because it isn't uniquely defined).

[toc] | [prev] | [next] | [standalone]


#145770 — Richard Damon weighs in... (Was: Question about use (and non-use) of "extern")

Fromgazelle@shell.xmission.com (Kenny McCormack)
Date2019-08-23 23:50 +0000
SubjectRichard Damon weighs in... (Was: Question about use (and non-use) of "extern")
Message-ID<qjpu3i$u1p$1@news.xmission.com>
In reply to#145769
In article <YgZ7F.223119$gM.160082@fx19.iad>,
Richard Damon  <Richard@Damon-Family.org> wrote:
...
>My understanding is that the __attribute__((weak)) applies at the time
>of (static) linking, not loading, thus does not affect the dynamic
>loading of a library.

Correct.  As a little bit of testing demonstrates.

>One BIG problem with his idea is a SHARED library doesn't have A calling
>program, but at any given time might have 0, 1, or 2 or more programs
>(dynamically) linked to it, so the library can't have linking options
>based on the calling program (because it isn't uniquely defined).

Irrelevant noise.  Not applicable to my situation.

-- 
When someone tells me he/she is a Christian I check to see if I'm
still in posession of my wallet.

[toc] | [prev] | [next] | [standalone]


#145813

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2019-08-27 15:03 -0700
Message-ID<qk49be$ac$1@dont-email.me>
In reply to#145732
On 8/20/2019 6:11 AM, Kenny McCormack wrote:
> Suppose you have multiple source files and you want to share access to a
> global (see footnote) variable.  The usual method is to define it in one
> module and "extern" it everywhere else.  E.g.:
> 
> /* In one module */
> int i;
> 
> /* Everywhere else */
> extern int i;
> 
> But what happens if you break this pattern?  I've determined that:
> 
> 1) If you "extern" it everywhere, you get "undefined variable" errors.

... unless you supply an initializer in one (and exactly one) of those 
extern-ed declarations. An explicit initializer would turn it into a 
definition, thus taking care of "undefined variable" errors.

> 2) If you "extern" it nowhere, it works fine.

...which is non-stnadard, but happens to be a popular extension among 
compilers with Unix roots.

> My question is: Is the later case OK?  Is it OK to just declare it normally
> in every module and not bother with "extern" ?

It is illegal from the formal point of view. The language standard does 
not allow that. The matter is rather well covered in widely available 
"Rationale for C99" document. The practice of allowing redundant 
[uninitialized] variable definitions comes from Unix compilers. At the 
time of standardization it was frowned upon by other platforms, which 
considered it too expensive to have the linker to seek and remove 
redundant definitions. In the end the committee agreed with the latter 
point of view and insisted on forcing the user to make no more than one 
single definition of each global variable.

Note that even in C99, when having the linker to do extra work was no 
longer considered a problem, the committee insisted on sticking to the 
same original logic when introducing inline functions into the language. 
C language requires the user to ensure that there's only one external 
definition of inline function in the program (compare that to C++ 
approach, which allows generating multiple external definitions and has 
linker removing extra copies later).

> I remember reading somewhere long ago that historically this works, but
> that it isn't guaranteed.

Exactly.

-- 
Best regards,
Andrey Tarasevich

[toc] | [prev] | [next] | [standalone]


#145922

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-09-03 05:57 -0700
Message-ID<86tv9ty1t4.fsf@mailhub.linuxsc.com>
In reply to#145813
Andrey Tarasevich <andreytarasevich@hotmail.com> writes:

> On 8/20/2019 6:11 AM, Kenny McCormack wrote:
>
>> Suppose you have multiple source files and you want to share
>> access to a global (see footnote) variable.  [how to do this?]
>>
>> 2) If you "extern" it nowhere, it works fine.
>
> ...which is non-stnadard, but happens to be a popular extension
> among compilers with Unix roots.

>> My question is:  Is the later case OK?  Is it OK to just declare
>> it normally in every module and not bother with "extern" ?
>
> It is illegal from the formal point of view.  The language standard
> does not allow that.

These statements are misleading.  An implementation may legally
support this pattern, with no diagnostics, and still conform to
the Standard.  Nothing in the Standard forbids that.  Neither does
the Standard require it, but that doesn't make it illegal, just
not advisable.  (More specifically, the behavior is undefined.)

> [...] The practice of allowing redundant [uninitialized] variable
> definitions comes from Unix compilers.  [...]

More significantly, it was the usual way of doing business in the
era of K&R C, and the C community at large expected it would work
even if not everyone followed it.

[toc] | [prev] | [next] | [standalone]


#145928

FromDavid Brown <david.brown@hesbynett.no>
Date2019-09-03 15:45 +0200
Message-ID<qklqqd$u5t$1@dont-email.me>
In reply to#145922
On 03/09/2019 14:57, Tim Rentsch wrote:
> Andrey Tarasevich <andreytarasevich@hotmail.com> writes:
> 
>> On 8/20/2019 6:11 AM, Kenny McCormack wrote:
>>
>>> Suppose you have multiple source files and you want to share
>>> access to a global (see footnote) variable.  [how to do this?]
>>>
>>> 2) If you "extern" it nowhere, it works fine.
>>
>> ...which is non-stnadard, but happens to be a popular extension
>> among compilers with Unix roots.
> 
>>> My question is:  Is the later case OK?  Is it OK to just declare
>>> it normally in every module and not bother with "extern" ?
>>
>> It is illegal from the formal point of view.  The language standard
>> does not allow that.
> 
> These statements are misleading.  An implementation may legally
> support this pattern, with no diagnostics, and still conform to
> the Standard.  Nothing in the Standard forbids that.  Neither does
> the Standard require it, but that doesn't make it illegal, just
> not advisable.  (More specifically, the behavior is undefined.)


If you have "int x;" in a translation unit (without any "static"
involved), that counts as an external definition of "x" with external
linkage.  (6.9.2p2 and 6.9.2p1).  If this identifier is used in an
expression (other than an unevaluated expression, such as a sizeof),
there must be exactly one definition of it (6.9p5).  These are "shall"
rules - they are as strong as the standards get.

I don't see anything in the standards (I'm looking at C11, but I don't
think these things have changed) requiring a conforming compiler to give
diagnostics about multiple "int x;" definitions in a program.  But as I
read it, it breaks a "shall" requirement, and that is as close to
"illegal" as you can get.  Effectively, you are no longer writing valid
C code, and it is undefined behaviour because the C standards only
define the behaviour of C code.

(Of course, real-world C compilers are often not strictly conforming,
and have extra features and misfeatures - supporting multiple "int x;"
definitions in a program being, IMHO, a misfeature.)

> 
>> [...] The practice of allowing redundant [uninitialized] variable
>> definitions comes from Unix compilers.  [...]
> 
> More significantly, it was the usual way of doing business in the
> era of K&R C, and the C community at large expected it would work
> even if not everyone followed it.
> 

Yes.  And if my history here is correct, this may be because it is the
way Fortran works, and therefore a familiar technique for many early C
programmers.

But the fact that most C compilers support it, and that a fair amount of
C code requires it, does not mean the language standard allows it.

[toc] | [prev] | [next] | [standalone]


#145942

FromKeith Thompson <kst-u@mib.org>
Date2019-09-03 11:13 -0700
Message-ID<lnblw1w8nl.fsf@kst-u.example.com>
In reply to#145928
David Brown <david.brown@hesbynett.no> writes:
[...]
> If you have "int x;" in a translation unit (without any "static"
> involved), that counts as an external definition of "x" with external
> linkage.  (6.9.2p2 and 6.9.2p1).  If this identifier is used in an
> expression (other than an unevaluated expression, such as a sizeof),
> there must be exactly one definition of it (6.9p5).  These are "shall"
> rules - they are as strong as the standards get.
[...]

The C standard uses "shall" in two very different ways.

A violation of a "shall" in a constraint (all constraints are explicitly
marked as such) requires a diagnostic, just like a syntax error.
*That's* as close as the C standard gets to saying something is
illegal/invalid/disallowed (aside from #error).

A violation of a "shall" outside a constraint, like the one in 6.9p5,
cause the code to have undefined behavior, with no diagnostic required.
In some cases, such rules can leave room for common extensions.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#145972

FromDavid Brown <david.brown@hesbynett.no>
Date2019-09-04 12:11 +0200
Message-ID<qko2kh$rlq$1@dont-email.me>
In reply to#145942
On 03/09/2019 20:13, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
> [...]
>> If you have "int x;" in a translation unit (without any "static"
>> involved), that counts as an external definition of "x" with external
>> linkage.  (6.9.2p2 and 6.9.2p1).  If this identifier is used in an
>> expression (other than an unevaluated expression, such as a sizeof),
>> there must be exactly one definition of it (6.9p5).  These are "shall"
>> rules - they are as strong as the standards get.
> [...]
> 
> The C standard uses "shall" in two very different ways.
> 
> A violation of a "shall" in a constraint (all constraints are explicitly
> marked as such) requires a diagnostic, just like a syntax error.
> *That's* as close as the C standard gets to saying something is
> illegal/invalid/disallowed (aside from #error).
> 
> A violation of a "shall" outside a constraint, like the one in 6.9p5,
> cause the code to have undefined behavior, with no diagnostic required.
> In some cases, such rules can leave room for common extensions.
> 

Thank you for the clarification.

Since violations of this particular requirement would be found at link
time, and it is not a mistake in the code in any given translation unit,
it would be very hard to impose a requirement of a diagnostic in a compiler.

[toc] | [prev] | [next] | [standalone]


#145982

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-09-04 08:18 -0400
Message-ID<qkoa2l$5k2$1@dont-email.me>
In reply to#145972
On 9/4/19 6:11 AM, David Brown wrote:
...
> Since violations of this particular requirement would be found at link
> time, and it is not a mistake in the code in any given translation unit,
> it would be very hard to impose a requirement of a diagnostic in a compiler.

Keep in mind that the standard only speaks of an implementation, not a
compiler. The linker is part of the implementation. When a diagnostic is
required (as it is not in this case), it's perfectly acceptable for that
diagnostic to be issued by the linker rather than the compiler.

[toc] | [prev] | [next] | [standalone]


#146055

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-09-06 02:25 -0700
Message-ID<86v9u5wzcv.fsf@mailhub.linuxsc.com>
In reply to#145942
Keith Thompson <kst-u@mib.org> writes:

> David Brown <david.brown@hesbynett.no> writes:
> [...]
>
>> If you have "int x;" in a translation unit (without any "static"
>> involved), that counts as an external definition of "x" with external
>> linkage.  (6.9.2p2 and 6.9.2p1).  If this identifier is used in an
>> expression (other than an unevaluated expression, such as a sizeof),
>> there must be exactly one definition of it (6.9p5).  These are "shall"
>> rules - they are as strong as the standards get.

David Brown: never in doubt, often in error.

> The C standard uses "shall" in two very different ways.
>
> A violation of a "shall" in a constraint (all constraints are
> explicitly marked as such) requires a diagnostic, just like a syntax
> error.  *That's* as close as the C standard gets to saying something
> is illegal/invalid/disallowed (aside from #error).
>
> A violation of a "shall" outside a constraint, like the one in
> 6.9p5, cause the code to have undefined behavior, with no diagnostic
> required.  In some cases, such rules can leave room for common
> extensions.

There is one, and only one, code situation that the ISO C
standard disallows:  accepting a translation unit that has an
unskipped #error directive.  (I have a vague memory of there
being something similar to this related to #pragma, but looking
at the Standard I couldn't find anything.  If someone finds
something I would appreciate hearing about it.)

After that, the next level of severity is situations that require
a diagnostic:  syntax errors and violating a 'shall' given as a
Constraint.  In practical terms this category may be subdivided
into two cases:  constructions that never have practical utility
(and we may reasonably expect that they are flagged as fatal
errors in most if not all implementations);  and constructions
that have a commonly held "misinterpretation" and which are often
used deliberately either in a nearly conforming mode or in a
conforming mode with a willingness to tolerate the mandated
warning.  An example of the latter case is the ?: operator,
available as an extension in both gcc and clang (and undoubtedly
others) where it does not give even a warning unless -pedantic is
used.

There are also a few other specific cases where diagnostics are
either recommended or required.  (I mention these only for the
sake of completeness.)

Situations that require a diagnostic are allowed in the sense
that they may be compiled and run if an implementation chooses to
do so, but the implementation must at least give notice that a
rule has been violated.

Nothing else is deemed "illegal" or "invalid" by the C standard.
Different constructions give implementations varying degrees of
freedom as to how they may be interpreted, including complete
freedom to do anything at all which is the case for multiply
defined global variables.  Even these extreme cases (the C
standard calls them "undefined behavior") are not in any sense
illegal or invalid.  Indeed, most if not all have been used
deliberately to accomplish something useful in a particular
environment even though they cannot be relied on in all (or even
most) environments.

Short summary:  if you want to write C code that works no matter
which platform it will be compiled and run on, there are a lot
of things to stay away from.  If the goal is more limited and
more modest, in many cases various "forbidden" constructions
will be just fine.

(Incidentally, I agree with what Keith was saying.  It seemed
worthwhile to approach the same subject area from a different
perspective.)

[toc] | [prev] | [next] | [standalone]


#146056

FromDavid Brown <david.brown@hesbynett.no>
Date2019-09-06 11:45 +0200
Message-ID<qkt9sn$a72$1@dont-email.me>
In reply to#146055
On 06/09/2019 11:25, Tim Rentsch wrote:
> Keith Thompson <kst-u@mib.org> writes:
> 
>> David Brown <david.brown@hesbynett.no> writes:
>> [...]
>>
>>> If you have "int x;" in a translation unit (without any "static"
>>> involved), that counts as an external definition of "x" with external
>>> linkage.  (6.9.2p2 and 6.9.2p1).  If this identifier is used in an
>>> expression (other than an unevaluated expression, such as a sizeof),
>>> there must be exactly one definition of it (6.9p5).  These are "shall"
>>> rules - they are as strong as the standards get.
> 
> David Brown: never in doubt, often in error.
> 

You may have failed to read my post very well, since you didn't notice
the clear doubt in it.  That happens when you read things with
prejudice.  Perhaps you are also unaware of the Usenet tradition of
saying what you think, with the expectation that others will say
differently if they think differently.  Sometimes - such as in this
thread - that means helpful and knowledgable people (James and Keith in
this case) give more information and improve the understanding of others.

> 
> Short summary:  if you want to write C code that works no matter
> which platform it will be compiled and run on, there are a lot
> of things to stay away from.  If the goal is more limited and
> more modest, in many cases various "forbidden" constructions
> will be just fine.
> 
> (Incidentally, I agree with what Keith was saying.  It seemed
> worthwhile to approach the same subject area from a different
> perspective.)
> 

Fair enough.

[toc] | [prev] | [next] | [standalone]


#146079

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2019-09-06 21:15 +0100
Message-ID<87d0gdxjt7.fsf@bsb.me.uk>
In reply to#145942
Keith Thompson <kst-u@mib.org> writes:
<cut>
> The C standard uses "shall" in two very different ways.
>
> A violation of a "shall" in a constraint (all constraints are explicitly
> marked as such) requires a diagnostic, just like a syntax error.
> *That's* as close as the C standard gets to saying something is
> illegal/invalid/disallowed (aside from #error).
>
> A violation of a "shall" outside a constraint, like the one in 6.9p5,
> cause the code to have undefined behavior, with no diagnostic required.
> In some cases, such rules can leave room for common extensions.

There's also the curious case of "shall" as used in the
runtime-contraints sections of Annex K.  These are program errors that
must be detected at run-time, but which lead only to a handler function
being called.

You can convert most (all?) of the Annex K functions into ones that
simply check their arguments and return an error indication when
something amiss is found by registering a "null" run-time constraint
handler that does nothing but return.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#145956

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-09-03 21:10 -0400
Message-ID<qkn2tg$6j6$1@dont-email.me>
In reply to#145928
On 9/3/19 9:45 AM, David Brown wrote:
> On 03/09/2019 14:57, Tim Rentsch wrote:
...
>> These statements are misleading.  An implementation may legally
>> support this pattern, with no diagnostics, and still conform to
>> the Standard.  Nothing in the Standard forbids that.  Neither does
>> the Standard require it, but that doesn't make it illegal, just
>> not advisable.  (More specifically, the behavior is undefined.)
> 
> 
> If you have "int x;" in a translation unit (without any "static"
> involved), that counts as an external definition of "x" with external
> linkage.  (6.9.2p2 and 6.9.2p1).  If this identifier is used in an
> expression (other than an unevaluated expression, such as a sizeof),
> there must be exactly one definition of it (6.9p5).  These are "shall"
> rules - they are as strong as the standards get.

No, the strongest requirements imposed by the standard include a
mandatory diagnostic. A diagnostic is mandatory for violation of a
"shall" or "shall not" statement only when it occurs in a Constraints
section - this one does not.


> I don't see anything in the standards (I'm looking at C11, but I don't
> think these things have changed) requiring a conforming compiler to give
> diagnostics about multiple "int x;" definitions in a program.  But as I
> read it, it breaks a "shall" requirement, and that is as close to
> "illegal" as you can get.

Which isn't very close. A fully conforming implementation of C could
issue all mandatory diagnostics, and then go ahead and complete
translation of the program normally. "Illegal" implies some punishment
if caught, and some effort to catch perpetrators, and that doesn't
apply, not even metaphorically, to any provision of the C standard.

...
> But the fact that most C compilers support it, and that a fair amount of
> C code requires it, does not mean the language standard allows it.

The fact that the C standard does not prohibit a fully conforming
implementation of C from accepting such code, means that the standard
does allow it. It allows a great deal, and prohibits very little.

[toc] | [prev] | [next] | [standalone]


#145973

FromDavid Brown <david.brown@hesbynett.no>
Date2019-09-04 12:21 +0200
Message-ID<qko36k$uok$1@dont-email.me>
In reply to#145956
On 04/09/2019 03:10, James Kuyper wrote:
> On 9/3/19 9:45 AM, David Brown wrote:
>> On 03/09/2019 14:57, Tim Rentsch wrote:
> ...
>>> These statements are misleading.  An implementation may legally
>>> support this pattern, with no diagnostics, and still conform to
>>> the Standard.  Nothing in the Standard forbids that.  Neither does
>>> the Standard require it, but that doesn't make it illegal, just
>>> not advisable.  (More specifically, the behavior is undefined.)
>>
>>
>> If you have "int x;" in a translation unit (without any "static"
>> involved), that counts as an external definition of "x" with external
>> linkage.  (6.9.2p2 and 6.9.2p1).  If this identifier is used in an
>> expression (other than an unevaluated expression, such as a sizeof),
>> there must be exactly one definition of it (6.9p5).  These are "shall"
>> rules - they are as strong as the standards get.
> 
> No, the strongest requirements imposed by the standard include a
> mandatory diagnostic. A diagnostic is mandatory for violation of a
> "shall" or "shall not" statement only when it occurs in a Constraints
> section - this one does not.
> 

Thanks for the clarification.

> 
>> I don't see anything in the standards (I'm looking at C11, but I don't
>> think these things have changed) requiring a conforming compiler to give
>> diagnostics about multiple "int x;" definitions in a program.  But as I
>> read it, it breaks a "shall" requirement, and that is as close to
>> "illegal" as you can get.
> 
> Which isn't very close. A fully conforming implementation of C could
> issue all mandatory diagnostics, and then go ahead and complete
> translation of the program normally. "Illegal" implies some punishment
> if caught, and some effort to catch perpetrators, and that doesn't
> apply, not even metaphorically, to any provision of the C standard.
> 

The word "illegal" is used in a wider sense than that in many
situations, including software development.  The C standard mentions
"illegal instructions" - if you execute an "illegal instruction" on a
cpu, you can expect a crash, exception, trap, or nasal demons, but not a
police officer and a court case.

> ...
>> But the fact that most C compilers support it, and that a fair amount of
>> C code requires it, does not mean the language standard allows it.
> 
> The fact that the C standard does not prohibit a fully conforming
> implementation of C from accepting such code, means that the standard
> does allow it. It allows a great deal, and prohibits very little.
> 

Fair enough.  I was under the impression that "shall" requirements were
equally strong, but as you and Keith have now shown me, there is a
significant difference between these requirements under "Constraints"
and "Semantics".  Multiple definitions of an identifier with /internal/
linkage inside a translation unit are a constraint violation, and thus
require a diagnostic.  Multiple definitions of an identifier with
/external/ linking and definitions in different translation units is
undefined behaviour - which means compilers can give it a defined
behaviour if they want.

Thanks for the information and explanation.

[toc] | [prev] | [next] | [standalone]


#145996

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2019-09-04 12:04 -0700
Message-ID<qkp1ru$vmf$1@dont-email.me>
In reply to#145922
On 9/3/2019 5:57 AM, Tim Rentsch wrote:
> Andrey Tarasevich <andreytarasevich@hotmail.com> writes:
> 
>> On 8/20/2019 6:11 AM, Kenny McCormack wrote:
>>
>>> Suppose you have multiple source files and you want to share
>>> access to a global (see footnote) variable.  [how to do this?]
>>>
>>> 2) If you "extern" it nowhere, it works fine.
>>
>> ...which is non-stnadard, but happens to be a popular extension
>> among compilers with Unix roots.
> 
>>> My question is:  Is the later case OK?  Is it OK to just declare
>>> it normally in every module and not bother with "extern" ?
>>
>> It is illegal from the formal point of view.  The language standard
>> does not allow that.
> 
> These statements are misleading.  An implementation may legally
> support this pattern, with no diagnostics, and still conform to
> the Standard.  Nothing in the Standard forbids that.  Neither does
> the Standard require it, but that doesn't make it illegal, just
> not advisable.  (More specifically, the behavior is undefined.)
> 

They are as "misleading" as any other statement that does not consist 
entirely of terms strictly defined by the language standard. The vague 
term "illegal", for example, is open to interpretation, as well as the 
original question "Is it OK?"

To rephrase it: a program that makes multiple definitions of the same 
object with external linkage is not *strictly conforming*. It can still 
be a plainly *conforming* program though.

-- 
Best regards,
Andrey Tarasevich

[toc] | [prev] | [next] | [standalone]


#145997

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-09-04 15:29 -0400
Message-ID<qkp3bn$9kp$1@dont-email.me>
In reply to#145996
On 9/4/19 3:04 PM, Andrey Tarasevich wrote:
> On 9/3/2019 5:57 AM, Tim Rentsch wrote:
>> Andrey Tarasevich <andreytarasevich@hotmail.com> writes:
>>
>>> On 8/20/2019 6:11 AM, Kenny McCormack wrote:
>>>
>>>> Suppose you have multiple source files and you want to share
>>>> access to a global (see footnote) variable.  [how to do this?]
>>>>
>>>> 2) If you "extern" it nowhere, it works fine.
>>>
>>> ...which is non-stnadard, but happens to be a popular extension
>>> among compilers with Unix roots.
>>
>>>> My question is:  Is the later case OK?  Is it OK to just declare
>>>> it normally in every module and not bother with "extern" ?
>>>
>>> It is illegal from the formal point of view.  The language standard
>>> does not allow that.
>>
>> These statements are misleading.  An implementation may legally
>> support this pattern, with no diagnostics, and still conform to
>> the Standard.  Nothing in the Standard forbids that.  Neither does
>> the Standard require it, but that doesn't make it illegal, just
>> not advisable.  (More specifically, the behavior is undefined.)
>>
> 
> They are as "misleading" as any other statement that does not consist 
> entirely of terms strictly defined by the language standard. The vague 
> term "illegal", for example, is open to interpretation, as well as the 
> original question "Is it OK?"
> 
> To rephrase it: a program that makes multiple definitions of the same 
> object with external linkage is not *strictly conforming*. It can still 
> be a plainly *conforming* program though.

While correct, that's not as specific as it could be. "strictly
conforming" is extremely strict, excluding all programs that, despite
being otherwise correct, have different behavior on different
implementations of C. "conforming" is extremely lenient - the only thing
it doesn't include is programs that have #error directives that survive
conditional compilation.

The most specific statement you can make in terms of the standard is
that such code has undefined behavior. A great many constructs that have
undefined behavior according to the C standard have behavior that, for
some implementations, is defined somewhere else, and there is code that
legitimately depends upon that alternative definition.

[toc] | [prev] | [next] | [standalone]


#146057

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-09-06 02:46 -0700
Message-ID<86r24twye0.fsf@mailhub.linuxsc.com>
In reply to#145996
Andrey Tarasevich <andreytarasevich@hotmail.com> writes:

> On 9/3/2019 5:57 AM, Tim Rentsch wrote:
>
>> Andrey Tarasevich <andreytarasevich@hotmail.com> writes:
>>
>>> On 8/20/2019 6:11 AM, Kenny McCormack wrote:
>>>
>>>> Suppose you have multiple source files and you want to share
>>>> access to a global (see footnote) variable.  [how to do this?]
>>>>
>>>> 2) If you "extern" it nowhere, it works fine.
>>>
>>> ...which is non-stnadard, but happens to be a popular extension
>>> among compilers with Unix roots.
>>>
>>>> My question is:  Is the later case OK?  Is it OK to just declare
>>>> it normally in every module and not bother with "extern" ?
>>>
>>> It is illegal from the formal point of view.  The language standard
>>> does not allow that.
>>
>> These statements are misleading.  An implementation may legally
>> support this pattern, with no diagnostics, and still conform to
>> the Standard.  Nothing in the Standard forbids that.  Neither does
>> the Standard require it, but that doesn't make it illegal, just
>> not advisable.  (More specifically, the behavior is undefined.)
>
> They are as "misleading" as any other statement that does not
> consist entirely of terms strictly defined by the language
> standard. [...]

Oh that's nonsense.  It's perfectly possible to give a reasonble
and not overly jargoned answer, as for example:

The C standard allows it to be okay if an implementation chooses
to act that way, and some implementations do (sometimes needing
particular compiler options).  However, the standard doesn't
require implementations to act in this way, or any way at all if
there is more than one case of "extern" being left off, so it
can't be counted on.  Unless there are special circumstances, and
you know what you're doing (and have a good reason for doing
it!), it's better to follow the usual pattern of using "extern"
in every separately compiled file where the variable is used, and
defining the variable (that is, leaving off the "extern") in
exactly one separately compiled file.  (By the way, the standard
uses "implementation" as an umbrella term to include what we
usually think of as compilers, linkers, etc.)

[toc] | [prev] | [next] | [standalone]


#146006

FromBonita Montero <Bonita.Montero@gmail.com>
Date2019-09-05 10:01 +0200
Message-ID<qkqfct$880$1@news.albasani.net>
In reply to#145732
Use C++17 and an inline-variable (https://bit.ly/2m1IjVH). ;-)

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.c


csiph-web