|
From: Jeffrey W. <nol...@gm...> - 2015-08-12 19:58:44
|
I'm catching an uninitialized access on a non-static variable that has
file scope in a C++ translation unit. I'm having trouble interpreting
the finding.
The variable that is triggering the uninitialized access is a simple
flag and I believe it is initialized:
bool g_flag = false;
The C++ object that uses it is in another translation unit, and it has
a init_pritority attribute.
I think I'm missing a finer detail on the confluence of the C++
standard intersecting default initialization tricks in the BSS segment
taken modulo what Valgrind sees (or believes it sees). I *think* it
also has something to do with the double value initialization
discussed in https://stackoverflow.com/questions/25742863/why-file-scope-static-variables-have-to-be-zero-initialized.
Can someone help me understand what's going on?
Thanks in advance.
|
|
From: Dan K. <da...@ke...> - 2015-08-12 20:09:42
|
On Wed, Aug 12, 2015 at 12:58 PM, Jeffrey Walton <nol...@gm...> wrote: > The C++ object that uses it is in another translation unit, and it has > a init_pritority attribute. File-scope or static C++ objects are the spawn of the devil. There is no reliable or portable way to control initialization order, even with init_priority, See e.g. http://stackoverflow.com/questions/3371968/attribute-init-priorityx-in-gcc - Dan |
|
From: David C. <dcc...@ac...> - 2015-08-12 22:29:16
|
On 8/12/2015 1:09 PM, Dan Kegel wrote: > On Wed, Aug 12, 2015 at 12:58 PM, Jeffrey Walton <nol...@gm...> wrote: >> The C++ object that uses it is in another translation unit, and it has >> a init_pritority attribute. > File-scope or static C++ objects are the spawn of the devil. > There is no reliable or portable way to control initialization order, > even with init_priority, See e.g. > http://stackoverflow.com/questions/3371968/attribute-init-priorityx-in-gcc > I got around this problem in C++ by defining an initialization order-independent method of creating global variables: /* nvalues.hpp */ class nv_base { public: nv_base(const my_string &name); const my_string &name(void) const { return _name; } ... private: my_string _name; static nv_base *first_nv; /* for hash table initialization */ nv_base *next_nv; /* traverse from first_nv */ nv_base(const nv_base &other); /* unimplemented */ nv_base &operator =(const nv_base &other); }; /* nvalues.cpp */ nv_base *nv_base::first_nv = 0; nv_base::nv_base(const my_string &name) { /* define a new named variable - must be global */ _name = name; next_nv = first_nv; /* link ourselves in */ first_nv = this; } class nv_integer : public nv_base { ... }; /* client.cpp */ nv_integer config_param("a_named_integer_value",5); As shown, client code derives from the base class, so I could have an integer value, a string value, etc. The traversal links allow high-level code to dump all of the values for debugging or saving state. There is a routine, invoked by main(), to prevent creation of these objects on the stack or with operator new (in my case, it also built a hash table for all the names). Access to the value in a named variable is only through a member function, so regardless of link order, when you access a variable it is initialized. Zero initialization is done before the program starts (ARM section 3.4), and global variables in a translation module are initialized before any code in that module (e.g. the constructors) is called. Originally I wrote this in 1991, for some of the very first C++ compilers. As features were added, I began to hit linkage order problems. I went to great lengths to make it link-order safe across platforms, compilers, and compiler versions, even defining a shadow set of utility routines for use only by this subsystem so there were no dependency loops. After all that, I used only one of these variables in 500,000 lines of code. Even though they were intended only for configuration parameters (the global list allowed me to dump the system configuration in the event of an error), I found that it was too difficult to isolate problems in code, or even to reuse it, when there was an arbitrary number of global variables influencing it. Now I refactor the code to avoid global variables, even if it means passing a value through multiple levels of existing code. I learned to pass a parameter block to a function as soon as the number of parameters got too high, or if I had to add a parameter to that function later. If I have to modify a function once, it's a safe bet that I will have to modify it again. It's much easier to add a field to a parameter block and define a good default value (in the constructor for C++ or the allocator function in C) than to modify every function call to have another argument. Also, I avoid default function parameter values in C++ because they make calling code harder to understand, and in a real product a function is called many more times than it is defined (i.e. once). Global variables are going to cause problems if you rely on the compiler, linker, or loader to initialize or destroy them in the order you want. Your code will always be vulnerable to the whims of another programmer. That programmer could be working on GCC, a run-time library, the OS, or even for you - when global variables change state at surprising times, every line of code in your program suddenly becomes a suspect. I've seen development of a suite of commercial products (millions of dollars per year in sales) be crippled by the use of global variables, even without considering initialization order. So even though I just told you how to guarantee that global variables in C++ are initialized before they are used, don't do it. :-) Refactoring sounds expensive but in the long run it is cheaper than debugging interactions between global variables. -- David Chapman dcc...@ac... Chapman Consulting -- San Jose, CA Software Development Done Right. www.chapman-consulting-sj.com |
|
From: Jeffrey W. <nol...@gm...> - 2015-08-13 05:18:37
|
On Wed, Aug 12, 2015 at 6:02 PM, David Chapman <dcc...@ac...> wrote:
> On 8/12/2015 1:09 PM, Dan Kegel wrote:
>> ...
>
> So even though I just told you how to guarantee that global variables in C++
> are initialized before they are used, don't do it. :-) Refactoring sounds
> expensive but in the long run it is cheaper than debugging interactions
> between global variables.
Thanks David.
Just venting here, but...
$ ls *.h *.cpp | wc -l
269
$ grep class *.h *.cpp | wc -l
1332
Of 1300+ classes and nearly 270 source files, there are 5 globals that
are sensitive to their initialization order. 3 are std::strings and 2
are C++ objects.
Its *really* pathetic the C++ language lacks a mechanism for me to say
"Object 1 depends upon String 1, 2, 3", and "Object 2 depends upon
Object 1 and String 1, 2, 3".
It's not like I'm asking the compiler to solve some NP-hard problem.
It does not have to solve any problem. The language just needs the
give me the ability to express a relative ordering among a handful of
objects.
The C/C++ committee does a lot of good, but they do some disingenuous
things at times. They are the same bone heads who thought it was a
good idea to crash a program when an assert fires. If you will recall,
an assert is debugging and diagnostic information, and its disabled in
release builds via the NDEBUG (no debug) macro. So an entire committee
thought it was clever to crash a program under a debugger. Sigh...
Jeff
|
|
From: Ivan S. J. <isj...@i1...> - 2015-08-12 20:24:46
|
On Wednesday 12 August 2015 15:58:36 Jeffrey Walton wrote: > The variable that is triggering the uninitialized access is a simple > flag and I believe it is initialized: > > bool g_flag = false; > > The C++ object that uses it is in another translation unit, and it has > a init_pritority attribute. > > I think I'm missing a finer detail on the confluence of the C++ > standard intersecting default initialization tricks in the BSS segment > taken modulo what Valgrind sees (or believes it sees). I *think* it > also has something to do with the double value initialization > discussed in https://stackoverflow.com/questions/25742863/why-file-scope-static-variables-have-to-be-zero-initialized. > > Can someone help me understand what's going on? It could be the initialzation order of the modules that causes the other translation unit to have its initializer run before g_flag is initialized. But g_flag should be initialized automatically by the compiler/linker before any code is run. There is another possibility: bool not_initialized; bool g_flag = false; int main(void) { g_flag = not_initialized; if(g_flag) printf("true"); else printf("false"); return 0; } The 'uninitializeness' is copied when memory is copied. Have you checked that this is not what is going on? /isj |
|
From: Jeffrey W. <nol...@gm...> - 2015-08-12 20:32:10
|
On Wed, Aug 12, 2015 at 4:09 PM, Dan Kegel <da...@ke...> wrote: > On Wed, Aug 12, 2015 at 12:58 PM, Jeffrey Walton <nol...@gm...> wrote: >> The C++ object that uses it is in another translation unit, and it has >> a init_pritority attribute. > > File-scope or static C++ objects are the spawn of the devil. > There is no reliable or portable way to control initialization order, > even with init_priority, See e.g. > http://stackoverflow.com/questions/3371968/attribute-init-priorityx-in-gcc I agree about the evil-ness of file scope C++ objects. Its been a chronic pain point. Even static locals have problems. I once had a logger class with an accessor: Logger& GetLogger() { static Logger s_logger; return s_logger; } Yep, logger crashed on program shutdown because the logger was using another static local that was declared in another translation unit and destroyed too soon. The GCC folks told me to use init_priority for these issues. See "Method to specify initialization order across translation units?" (https://gcc.gnu.org/ml/gcc-help/2015-08/msg00025.html). Jeff |
|
From: Dan K. <da...@ke...> - 2015-08-12 20:41:17
|
On Wed, Aug 12, 2015 at 1:32 PM, Jeffrey Walton <nol...@gm...> wrote: > The GCC folks told me to use init_priority for these issues. See > "Method to specify initialization order across translation units?" > (https://gcc.gnu.org/ml/gcc-help/2015-08/msg00025.html). I bet they were thinking "... and get rid of those statics" :-) Have you tried making a toy example that exhibits the problem? Posting one of those would save lots of questions. - Dan |
|
From: Bart V. A. <bva...@ac...> - 2015-08-13 05:38:48
|
On 08/12/15 22:18, Jeffrey Walton wrote: > Its *really* pathetic the C++ language lacks a mechanism for me to say > "Object 1 depends upon String 1, 2, 3", and "Object 2 depends upon > Object 1 and String 1, 2, 3". What's wrong with the singleton pattern ? When using the singleton pattern non-circular dependencies are resolved at runtime without having to specify the dependencies explicitly to the compiler. Bart. |
|
From: Dan K. <da...@ke...> - 2015-08-13 06:09:51
|
On Wed, Aug 12, 2015 at 10:38 PM, Bart Van Assche <bva...@ac...> wrote: > What's wrong with the singleton pattern ? Less, now :-) See http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/ - Dan |
|
From: Jeffrey W. <nol...@gm...> - 2015-08-13 07:43:26
|
On Thu, Aug 13, 2015 at 1:38 AM, Bart Van Assche <bva...@ac...> wrote: > On 08/12/15 22:18, Jeffrey Walton wrote: >> >> Its *really* pathetic the C++ language lacks a mechanism for me to say >> "Object 1 depends upon String 1, 2, 3", and "Object 2 depends upon >> Object 1 and String 1, 2, 3". > > > What's wrong with the singleton pattern ? When using the singleton pattern > non-circular dependencies are resolved at runtime without having to specify > the dependencies explicitly to the compiler. > I could be wrong, but I think its the wrong tool for the job. I don't have an issue with a mutithreaded program racing to create a single object at runtime. Rather, its startup code executed at load time, which I believe is guaranteed to be single threaded (or thread safe). So the only problem that needs to be solved is the order in which they are initialized. Jeff |
|
From: Jeffrey W. <nol...@gm...> - 2015-08-13 07:47:42
|
> Can someone help me understand what's going on? > I really enjoyed the sidebars. (Thanks for tolerating the color commentary). But to get back to the question on the findings, why would Valgrind complain a boolean value is not initialized, even though its initialized to false in the source code and backed via BSS? And is this a legitimate finding? Jeff |
|
From: Dan K. <da...@ke...> - 2015-08-13 08:03:57
|
Am 13.08.2015 12:48 vorm. schrieb "Jeffrey Walton" <nol...@gm...>: >... > But to get back to the question on the findings, why would Valgrind > complain a boolean value is not initialized, even though its > initialized to false in the source code and backed via BSS? It would help if you could post a complete example so others could see it in action. Have you tried hacking it down until it fits in a teacup? - Dan |
|
From: Julian S. <js...@ac...> - 2015-08-13 13:19:17
|
On 13/08/15 10:03, Dan Kegel wrote: > It would help if you could post a complete example so others could see it > in action. Have you tried hacking it down until it fits in a teacup? +1 for that. J |
|
From: David C. <dcc...@ac...> - 2015-08-13 09:10:45
|
On 8/12/2015 10:18 PM, Jeffrey Walton wrote:
> On Wed, Aug 12, 2015 at 6:02 PM, David Chapman <dcc...@ac...> wrote:
>> On 8/12/2015 1:09 PM, Dan Kegel wrote:
>>> ...
>> So even though I just told you how to guarantee that global variables in C++
>> are initialized before they are used, don't do it. :-) Refactoring sounds
>> expensive but in the long run it is cheaper than debugging interactions
>> between global variables.
> Thanks David.
>
> Just venting here, but...
>
> $ ls *.h *.cpp | wc -l
> 269
> $ grep class *.h *.cpp | wc -l
> 1332
>
> Of 1300+ classes and nearly 270 source files, there are 5 globals that
> are sensitive to their initialization order. 3 are std::strings and 2
> are C++ objects.
>
> Its *really* pathetic the C++ language lacks a mechanism for me to say
> "Object 1 depends upon String 1, 2, 3", and "Object 2 depends upon
> Object 1 and String 1, 2, 3".
>
> It's not like I'm asking the compiler to solve some NP-hard problem.
> It does not have to solve any problem. The language just needs the
> give me the ability to express a relative ordering among a handful of
> objects.
>
You might have only five variables, but the next person will have a few
more, and the next will have still more... I doubt that any standards
committee would provide a solution that would work only for a small set
like that. Also, you can get dependency loops very quickly: "object 1
depends on object 2, object 2 depends on object 3, object 3 depends on
object 1." That's basically what happened to me, and I had to rewrite
an awful lot of code to get rid of it. If the dependency loop goes
through an outside library, or worse yet appears just by linking a set
of outside libraries, you're stuck.
The software package that I mentioned had hundreds of global variables
(I didn't have the nerve to count them all, but the company founder
thought they were a great way to avoid the overhead of passing
parameters to functions). Resolving initialization order dependencies
would have been a nightmare. I don't think initialization order was a
problem in that particular package, but "hey - who changed that
variable???" was a big deal. The code could take hours to run, so
debugging could be very slow and tedious.
--
David Chapman dcc...@ac...
Chapman Consulting -- San Jose, CA
Software Development Done Right.
www.chapman-consulting-sj.com
|
|
From: Jeffrey W. <nol...@gm...> - 2015-08-13 11:29:30
|
>> Just venting here, but... >> >> $ ls *.h *.cpp | wc -l >> 269 >> $ grep class *.h *.cpp | wc -l >> 1332 >> >> Of 1300+ classes and nearly 270 source files, there are 5 globals that >> are sensitive to their initialization order. 3 are std::strings and 2 >> are C++ objects. >> >> Its *really* pathetic the C++ language lacks a mechanism for me to say >> "Object 1 depends upon String 1, 2, 3", and "Object 2 depends upon >> Object 1 and String 1, 2, 3". >> >> It's not like I'm asking the compiler to solve some NP-hard problem. >> It does not have to solve any problem. The language just needs the >> give me the ability to express a relative ordering among a handful of >> objects. >> > > You might have only five variables, but the next person will have a few > more, and the next will have still more... I doubt that any standards > committee would provide a solution that would work only for a small set like > that. Yeah, but that's just bikeshedding, no? (http://bikeshed.com/). Static variables simply exist, and the C++ committee will not be able to wish them away. Any GNU mirror (like ftp://gnu.mirror.iweb.com/) or code repository (like GitHub or Google Code) will demonstrate it in practice. As long as the language provides a way for me to express A depends on B, then the language's job is done (some hand waiving). If the committee claims I should not be able to do that, then that's an explicit bikeshed moment. Or if they don't give it to me, then that an implicit bikeshed moment. Or if the committee claims I should do X (like X = Singleton with a smart pointer and dynamic allocation), then that's a bikeshed moment, too. (I personally despise the memory manager, and the run time costs associated with going to the memory manager. That's why I prefer fixed, static allocations). > Also, you can get dependency loops very quickly: "object 1 depends > on object 2, object 2 depends on object 3, object 3 depends on object 1." Agreed. Directed graphs without loops is my problem, not the language's or compiler's problem. Its no different than header loops. > That's basically what happened to me, and I had to rewrite an awful lot of > code to get rid of it. If the dependency loop goes through an outside > library, or worse yet appears just by linking a set of outside libraries, > you're stuck. This is where the hand waiving comes in with "provide a way for me to express A depends on B". Sometimes I need to say, "Within my library, Object A depends on Object B". And other times I need to say "My library depends on libstdc++ (GNU runtime) or libc++ (LLVM runtime)". I think both represent real world use cases (q.v.), and both are reasonable. My list would also include a way to express "My Object A depends upon Library X". That use case covers users of non-standard libraries. I think it represents a real world use case, and its reasonable, too. > The software package that I mentioned had hundreds of global variables (I > didn't have the nerve to count them all, but the company founder thought > they were a great way to avoid the overhead of passing parameters to > functions). Oh man, my heart goes out to you. (I'm not throwing stones. Fresh out of college, I used to do that too. I'm kind of lazy, and I still do it for my POCs). Jeff |
|
From: Milian W. <ma...@mi...> - 2015-08-13 13:05:25
Attachments:
signature.asc
|
On Thursday, August 13, 2015 07:29:22 AM Jeffrey Walton wrote: > >> Just venting here, but... > >> > >> $ ls *.h *.cpp | wc -l > >> 269 > >> $ grep class *.h *.cpp | wc -l > >> 1332 > >> > >> Of 1300+ classes and nearly 270 source files, there are 5 globals that > >> are sensitive to their initialization order. 3 are std::strings and 2 > >> are C++ objects. > >> > >> Its *really* pathetic the C++ language lacks a mechanism for me to say > >> "Object 1 depends upon String 1, 2, 3", and "Object 2 depends upon > >> Object 1 and String 1, 2, 3". > >> > >> It's not like I'm asking the compiler to solve some NP-hard problem. > >> It does not have to solve any problem. The language just needs the > >> give me the ability to express a relative ordering among a handful of > >> objects. > > > > You might have only five variables, but the next person will have a few > > more, and the next will have still more... I doubt that any standards > > committee would provide a solution that would work only for a small set > > like that. > > Yeah, but that's just bikeshedding, no? (http://bikeshed.com/). > > Static variables simply exist, and the C++ committee will not be able > to wish them away. Any GNU mirror (like ftp://gnu.mirror.iweb.com/) or > code repository (like GitHub or Google Code) will demonstrate it in > practice. > > As long as the language provides a way for me to express A depends on > B, then the language's job is done (some hand waiving). If the > committee claims I should not be able to do that, then that's an > explicit bikeshed moment. Or if they don't give it to me, then that an > implicit bikeshed moment. > > Or if the committee claims I should do X (like X = Singleton with a > smart pointer and dynamic allocation), then that's a bikeshed moment, > too. (I personally despise the memory manager, and the run time costs > associated with going to the memory manager. That's why I prefer > fixed, static allocations). Just a side note: Static globals in C++ are OK as long as they have a trivial constructor. As soon as you do anything fancy and code needs to run upon initialization, then you pay dearly due to the static initialization order fiasco - but also this significantly increases startup time of your application, as *everything* will be initialized before main is run. Because of this alone, many C++ libraries like Qt right-out reject any code that adds global statics with non-trivial constructors. So if you are saying you care about the runtime cost of using a memory manager, then you should re-think whether you really want to keep using global statics. Most notably, look at the code that is created for static initialization: Often, you'll incur several cache misses during static initialization as code from all over needs to be paged in. My suggestions is to stop using static globals altogether - and that does _not_ mean you have to use heap allocated objects! Foo& foo() { static Foo foo; return foo; } This will be constructed on first use, is thread safe, and you can specifically define the construction order by calling foo somewhere in your code. Bye -- Milian Wolff ma...@mi... http://milianw.de |
|
From: Jeffrey W. <nol...@gm...> - 2015-08-13 13:11:44
|
>
> My suggestions is to stop using static globals altogether - and that does
> _not_ mean you have to use heap allocated objects!
>
> Foo& foo()
> {
> static Foo foo;
> return foo;
> }
>
> This will be constructed on first use, is thread safe, and you can
> specifically define the construction order by calling foo somewhere in your
> code.
>
Yeah, I tried that pattern once. I've since learned that the pattern
above is just another instance of the initialization order fiasco.
I had a dependency where one static local had a dependency on another
static local. As fate would have it, I got a bad draw and my Foo
object crashed on destruction because it was using a Bar object that
had already been destroyed.
Al we have managed to do since C++98 (maybe earlier) is move the
problem around because the C++ language has not given us the tools we
need to address the problem.
Jeff
|
|
From: Dan K. <da...@ke...> - 2015-08-13 16:06:37
|
On Thu, Aug 13, 2015 at 6:11 AM, Jeffrey Walton <nol...@gm...> wrote: > Al we have managed to do since C++98 (maybe earlier) is move the > problem around because the C++ language has not given us the tools we > need to address the problem. What part of "stop doing that" does C++ get in the way of? - Dan |
|
From: Jeffrey W. <nol...@gm...> - 2015-08-13 17:28:42
|
On Thu, Aug 13, 2015 at 12:06 PM, Dan Kegel <da...@ke...> wrote: > On Thu, Aug 13, 2015 at 6:11 AM, Jeffrey Walton <nol...@gm...> wrote: >> Al we have managed to do since C++98 (maybe earlier) is move the >> problem around because the C++ language has not given us the tools we >> need to address the problem. > > What part of "stop doing that" does C++ get in the way of? The objects simply exist, and telling someone "don't do that" is wishful thinking at best. That's the implicit bikeshedding I was talking about. And converting the file-scoped globals into locals with accessors suffers the same problem on the destructor side. So the problem was not fixed; rather it was just moved around. Jeff |
|
From: Patrick J. L. <lop...@gm...> - 2015-08-13 17:39:06
|
On Thu, Aug 13, 2015 at 10:28 AM, Jeffrey Walton <nol...@gm...> wrote: > > And converting the file-scoped globals into locals with accessors > suffers the same problem on the destructor side. Not true. The C++ spec guarantees destructors will run in the opposite order of constructors in most cases. The Meyers Singleton is such a case. (So are global objects, incidentally. Global construction order is unspecified, but whatever the order is, global destruction order is guaranteed to be the opposite.) - Pat |
|
From: David C. <dcc...@ac...> - 2015-08-13 18:05:45
|
On 8/13/2015 10:28 AM, Jeffrey Walton wrote:
> On Thu, Aug 13, 2015 at 12:06 PM, Dan Kegel <da...@ke...> wrote:
>> On Thu, Aug 13, 2015 at 6:11 AM, Jeffrey Walton <nol...@gm...> wrote:
>>> Al we have managed to do since C++98 (maybe earlier) is move the
>>> problem around because the C++ language has not given us the tools we
>>> need to address the problem.
>> What part of "stop doing that" does C++ get in the way of?
> The objects simply exist, and telling someone "don't do that" is
> wishful thinking at best. That's the implicit bikeshedding I was
> talking about.
>
> And converting the file-scoped globals into locals with accessors
> suffers the same problem on the destructor side. So the problem was
> not fixed; rather it was just moved around.
>
"Bikeshedding" is not the analogy I would apply; it's more like "camel's
nose in the tent". The problem sounds tractable as long as it is kept
small, but people will naturally want more and more. Even the GCC
init_priority extension is limited to 65435 (65535 - 101 + 1) priority
levels. What if someone has thousands of global variables to order
(e.g. an embedded system with no memory allocator)? What if the
libraries don't play nice and all of them ask for priority 101? What if
priorities 101 to 10000 are all taken, and one more variable needs to be
added in the middle?
My code "simply existed" and it had initialization order problems. I
rewrote it. That cost money, but I have never regretted it.
--
David Chapman dcc...@ac...
Chapman Consulting -- San Jose, CA
Software Development Done Right.
www.chapman-consulting-sj.com
|
|
From: John R. <jr...@bi...> - 2015-08-13 20:56:30
|
On 08/13/2015 12:47 AM, Jeffrey Walton wrote: > ...why would Valgrind > complain a boolean value is not initialized, even though its > initialized to false in the source code and backed via BSS? The most common reason is because some uninitialized value was assigned to (or copied into) the value in question. Of course you probably claim that this is impossible, but an unknown bug enables almost anything. Be sure to run with --track-origins=yes. As others have noted, if you cannot post a concrete example that illustrates the problem then you are not worth our time anymore. |
|
From: Jeffrey W. <nol...@gm...> - 2015-08-13 22:30:23
|
>> ...why would Valgrind >> complain a boolean value is not initialized, even though its >> initialized to false in the source code and backed via BSS? > > The most common reason is because some uninitialized value > was assigned to (or copied into) the value in question. Of course you probably > claim that this is impossible, but an unknown bug enables almost anything. > Be sure to run with --track-origins=yes. > > As others have noted, if you cannot post a concrete example > that illustrates the problem then you are not worth our time anymore. Thanks. I tracked it down to a one-liner ASM statement. The CPUID instruction's ASM block was missing volatile. I guess the optimizer removed it, which confused the machinery. (The other values were initialized, like the global flags and the word array used to represent %EAX - %EDX). Thanks again. Jeff |
|
From: Dan K. <da...@ke...> - 2015-08-13 22:40:16
|
On Thu, Aug 13, 2015 at 3:30 PM, Jeffrey Walton <nol...@gm...> wrote: > I tracked it down to a one-liner ASM statement. The CPUID > instruction's ASM block was missing volatile. I guess the optimizer > removed it, which confused the machinery. (The other values were > initialized, like the global flags and the word array used to > represent %EAX - %EDX). Sweet, thanks for letting us know what the culprit was! Now that you've tracked it down, can you publish a slimmed down case? If you think the optimizer's at fault, maybe we can file a bug for that. - Dan |