Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #145732 > unrolled thread
| Started by | gazelle@shell.xmission.com (Kenny McCormack) |
|---|---|
| First post | 2019-08-20 13:11 +0000 |
| Last post | 2019-09-06 20:24 +0200 |
| Articles | 20 on this page of 42 — 15 participants |
Back to article view | Back to comp.lang.c
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 →
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2019-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]
| From | gazelle@shell.xmission.com (Kenny McCormack) |
|---|---|
| Date | 2019-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]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2019-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]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2019-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]
| From | gazelle@shell.xmission.com (Kenny McCormack) |
|---|---|
| Date | 2019-08-23 23:50 +0000 |
| Subject | Richard 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]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2019-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2019-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-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]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2019-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2019-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]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2019-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-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]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2019-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]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2019-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2019-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]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2019-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