Re: C++ module ordering (was: segmentation fault on GiNaC-1.2.0 using MinGW on Win XP)
On 6 May 2004, Ian Lance Taylor wrote:
Please see <http://www.ginac.de/lists/ginac-devel/msg00623.html>.
Those bits are the end of my message weren't actually written by me. They were written by some of the C++ compiler hackers at Cygnus.
So it remains a mystery what was meant by "full runtime dependency analysis [...] with no linker mods"? Sad.
Are you familiar with the init_priority attribute supported by g++? It seems to me that it handles most of the problems associated with static object initialization order. http://gcc.gnu.org/onlinedocs/gcc-3.4.0/gcc/C---Attributes.html#C++%20Attrib...
Sure, but that is only pampering about the real problem: Who establishes the PRIORITY variables? The programmer would have to do it manually. Any programmer is likely to get it wrong if confronted with several hundreds or even thousands of modules. Working with an automated mechanism is much less prone to errors. Hence init_priority is not at all an acceptable solution, IMNSHO. A while ago, I've been debugging an industrial application where the linker line was basically rearranged automatically based on a self-made scheme: a script was extracting dependency ordering information scattered by the programmer. That solution is equivalant to GCC's init_priority. The lesson learned from that experience are: 1) Most professional C++ programmers are not aware of there being a problem. Really. :-( 2) Even if they are, they are unlikely to get it right. #-( 3) If they don't get it right, debugging code which hasn't even started running yet is intersting. :-/ Best wishes -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
"Richard B. Kreckel" <kreckel@ginac.de> writes:
So it remains a mystery what was meant by "full runtime dependency analysis [...] with no linker mods"? Sad.
Oh, no, I know what that means. It means that the compiler itself looks at the constructor and determines what other objects it references. The compiler itself then ensures that any constructor for those other objects are run first. The compiler should be able to do a more reliable job than the linker. One way to do that would for the compiler to generate entries in a special section for each global constructor. Each entry in the section would simply be the name of the global constructor and the name of another object upon which it depends. The linker could then gather that information together and build a topographical map, and use that map to construct a constructor ordering, much as is done in Bruno's existing patch. Circular dependencies would be detected at link time.
Are you familiar with the init_priority attribute supported by g++? It seems to me that it handles most of the problems associated with static object initialization order. http://gcc.gnu.org/onlinedocs/gcc-3.4.0/gcc/C---Attributes.html#C++%20Attrib...
Sure, but that is only pampering about the real problem: Who establishes the PRIORITY variables? The programmer would have to do it manually. Any programmer is likely to get it wrong if confronted with several hundreds or even thousands of modules. Working with an automated mechanism is much less prone to errors. Hence init_priority is not at all an acceptable solution, IMNSHO.
Well, even with many modules, you can divide and conquer the problem. Normally modules come in groups, and you can determine a topographical sort of the group. Then you can assign number ranges to the groups. Then within each group, you can do the right thing. If there are circles in the group graph, then you have a problem, but in that case I suspect that you have a deeper design problem as well. The other simple approach is to not use global constructors, or at least not global constructors in which there are cross-module dependencies. You instead pay a cost to check that the objects are initialized before they are used. In practice I suspect this cost would be quite small. Ian
Ian Lance Taylor <ian@wasabisystems.com> writes: | "Richard B. Kreckel" <kreckel@ginac.de> writes: | | > So it remains a mystery what was meant by "full runtime dependency | > analysis [...] with no linker mods"? Sad. | | Oh, no, I know what that means. It means that the compiler itself | looks at the constructor and determines what other objects it | references. The compiler itself then ensures that any constructor for | those other objects are run first. The compiler should be able to do | a more reliable job than the linker. | | One way to do that would for the compiler to generate entries in a | special section for each global constructor. Each entry in the | section would simply be the name of the global constructor and the | name of another object upon which it depends. The linker could then | gather that information together and build a topographical map, and | use that map to construct a constructor ordering, much as is done in | Bruno's existing patch. Circular dependencies would be detected at | link time. | | > > Are you familiar with the init_priority attribute supported by g++? | > > It seems to me that it handles most of the problems associated with | > > static object initialization order. | > > http://gcc.gnu.org/onlinedocs/gcc-3.4.0/gcc/C---Attributes.html#C++%20Attrib... | > | > Sure, but that is only pampering about the real problem: Who establishes | > the PRIORITY variables? The programmer would have to do it manually. | > Any programmer is likely to get it wrong if confronted with several | > hundreds or even thousands of modules. Working with an automated | > mechanism is much less prone to errors. Hence init_priority is not at all | > an acceptable solution, IMNSHO. | | Well, even with many modules, you can divide and conquer the problem. | Normally modules come in groups, and you can determine a topographical | sort of the group. Then you can assign number ranges to the groups. | Then within each group, you can do the right thing. I suspect Ricky's point is preceily that if that sektch of algorithm is workable, then it should be tajen care of by the compiler -- those are simply too much of low level details and the compiler/linker has more information that it could pass around. | If there are | circles in the group graph, then you have a problem, but in that case | I suspect that you have a deeper design problem as well. yep, but then it would be helpful if such circles are reported by the compiler/linker as it is processing the translation/instantiation units. In presence of templates and "deferred" instantiations, that even makes more sense where one gets all sorts of headaches. See http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#362 http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#270 | The other simple approach is to not use global constructors, or at | least not global constructors in which there are cross-module | dependencies. You instead pay a cost to check that the objects are | initialized before they are used. In practice I suspect this cost | would be quite small. Well, I'm not sure :-) -- Gaby
"Richard B. Kreckel" <kreckel@ginac.de> writes: | On 6 May 2004, Ian Lance Taylor wrote: | > > Please see <http://www.ginac.de/lists/ginac-devel/msg00623.html>. | > | > Those bits are the end of my message weren't actually written by me. | > They were written by some of the C++ compiler hackers at Cygnus. | | So it remains a mystery what was meant by "full runtime dependency | analysis [...] with no linker mods"? Sad. | | > Are you familiar with the init_priority attribute supported by g++? | > It seems to me that it handles most of the problems associated with | > static object initialization order. | > http://gcc.gnu.org/onlinedocs/gcc-3.4.0/gcc/C---Attributes.html#C++%20Attrib... | | Sure, but that is only pampering about the real problem: Who establishes | the PRIORITY variables? The programmer would have to do it manually. | Any programmer is likely to get it wrong if confronted with several | hundreds or even thousands of modules. Working with an automated | mechanism is much less prone to errors. Hence init_priority is not at all | an acceptable solution, IMNSHO. I agree. | A while ago, I've been debugging an industrial application where the | linker line was basically rearranged automatically based on a self-made | scheme: a script was extracting dependency ordering information scattered | by the programmer. That solution is equivalant to GCC's init_priority. | The lesson learned from that experience are: | | 1) Most professional C++ programmers are not aware of there being a | problem. Really. :-( I think that is far too excessive. | 2) Even if they are, they are unlikely to get it right. #-( | | 3) If they don't get it right, debugging code which hasn't even started | running yet is intersting. :-/ agreed too. -- Gaby
On 9 May 2004, Gabriel Dos Reis wrote: [...]
| 1) Most professional C++ programmers are not aware of there being a | problem. Really. :-(
I think that is far too excessive.
Well, I suppose we can reach agreement by putting that attribute in quotes. ;-)
| 2) Even if they are, they are unlikely to get it right. #-( | | 3) If they don't get it right, debugging code which hasn't even started | running yet is intersting. :-/
agreed too.
Of course such programs can be debugged the way Ian has described. In fact, you normally are able to obtain a stack backtrace which makes the problem apparent. (That is, unless you are completely clueless and the debugging version is built differently and doesn't core as opposed to the release version. (Oops, we've just had this case in GiNaC the other way round, haven't we?)) Let me mention that the dependency problem may be somewhat aggravated in the situation where a stack of libraries sit on top of each other and where static objects from the higher libs depend on properly initialized static objects from the lower levels. I suppose this could be done, too, by the compiler? <offtopic> Anyway, that whole static domain is IMO somewhat uncared for in C++. Which is unfortunate. It does give other environments a real competitive advantage. Without claiming actual experience, I've frequently pondered whether a class static section (of Java fame) wouldn't be quite useful. Useful for things less mundane than establishing initialization orders, of course. But that is another story. </offtopic> Luck -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
participants (3)
-
Gabriel Dos Reis
-
Ian Lance Taylor
-
Richard B. Kreckel