Re: C/C++ Option to Initialize Variables?
On 18/02/13 18:08, Robert Dewar wrote: Forgive me, but I don't see where anything is guaranteed to be zero'd before use. I'm likely wrong somewhere since you disagree. http://en.wikipedia.org/wiki/.bss This is about what happens to work, and specifically notes that it is not part of the C standard. There is a big difference between programs that obey the standard, and those that don't but happen to work on some systems. The latter programs have latent bugs that can definitely cause trouble. A properly written C program should avoid uninitialized variables, just as a properly written Ada program should avoid them. In GNAT, we have found the Initialize_Scalars pragma to be very useful in finding uninitialized variables. It causes all scalars to be initialized using a specified bit pattern that can be specified at link time, and modified at run-time. If you run a program with different patterns, it should give the same result, if it does not, you have an uninitialized variable or other non-standard aspect in your program which should be tracked down and fixed. Note that the BSS-is-always-zero guarantee often does not apply when embedded programs are restarted, so it is by no means a universal guarantee. I believe the standards require that all statically allocated data without an explicit initialisation are initialised to a /value/ of zero. The standards do not require values of zero to actually be zero bits - it is legal for null pointers, 0 integers, and 0.0 floats and doubles to have different representations. It is also perfectly legal for the compiler to put uninitialised data somewhere other than ".bss". But the standards do guarantee that a definition "int x;" has the same effect as "int x = 0;" - and similarly for all other statically allocated data. In embedded systems, any C startup code (the code that is run before main() is called) that does not clear the bss is dangerously broken. (I know of no real-world embedded processors where 0 is /not/ represented as zero bits.) There are a few toolchains that /are/ broken in this way - Texas Instruments's "Code Composer" is a prime example. The manual mentions this briefly at one point - to paraphrase, "the C startup code does not clear the bss at startup. We know this is against every C standard - but we never claimed to follow any particular C standard anyway". So if you know that you will be working with broken compilers that don't follow such fundamental parts of the C standards, then you should not rely on the automatic zero initialisation. But if you are using real working toolchains, then you (as an embedded programmer) /should/ rely on it - because it leads to smaller and faster code than explicitly initialising them to zero. (Of course, sometimes you want to be explicit in initialising to zero for clarity of the program - this trumps efficiency every time.)
Re: C/C++ Option to Initialize Variables?
Hi, On Mon, 18 Feb 2013, Alexander Monakov wrote: > On Mon, 18 Feb 2013, Michael Matz wrote: > > Automatic variables, as they are on the stack, are unlikely to usually get > > the value 0 out of pure luck, so an option to initialize them to 0xDEADBEAF > > doesn't make much sense. > > Hm, but the following comment from init-regs.c indicates that GCC will set > some uninitialized vars to zero, except at -O0: Yes, that's for pseudos, i.e. scalar automatic variables, doesn't work for may-uninitialized or aggregates and would be unnecessary with -Werror, as must-uninitialized can be and are detected without false positives. The value could be made configurable but I wouldn't see the point. Ciao, Michael.
Re: C/C++ Option to Initialize Variables?
Wrong. It specifies that objects with static storage duration that aren't explicitely initialized are initialized with null pointers, or zeros depending on type. 6.7.8.10. OK, that means that the comments of my last mesage don't apply to variables of this type. So they should at least optionally be excluded from any feature to initialize variables Hence if .bss is to be used to place such objects then the runtime system _must_ make sure that it's zero initialized.
Re: C/C++ Option to Initialize Variables?
Forgive me, but I don't see where anything is guaranteed to be zero'd before use. I'm likely wrong somewhere since you disagree. http://en.wikipedia.org/wiki/.bss This is about what happens to work, and specifically notes that it is not part of the C standard. There is a big difference between programs that obey the standard, and those that don't but happen to work on some systems. The latter programs have latent bugs that can definitely cause trouble. A properly written C program should avoid uninitialized variables, just as a properly written Ada program should avoid them. In GNAT, we have found the Initialize_Scalars pragma to be very useful in finding uninitialized variables. It causes all scalars to be initialized using a specified bit pattern that can be specified at link time, and modified at run-time. If you run a program with different patterns, it should give the same result, if it does not, you have an uninitialized variable or other non-standard aspect in your program which should be tracked down and fixed. Note that the BSS-is-always-zero guarantee often does not apply when embedded programs are restarted, so it is by no means a universal guarantee.
Re: C/C++ Option to Initialize Variables?
On Mon, 18 Feb 2013, Michael Matz wrote: > Automatic variables, as they are on the stack, are unlikely to usually get > the value 0 out of pure luck, so an option to initialize them to 0xDEADBEAF > doesn't make much sense. Hm, but the following comment from init-regs.c indicates that GCC will set some uninitialized vars to zero, except at -O0: /* Check all of the uses of pseudo variables. If any use that is MUST uninitialized, add a store of 0 immediately before it. For subregs, this makes combine happy. For full word regs, this makes other optimizations, like the register allocator and the reg-stack happy as well as papers over some problems on the arm and other processors where certain isa constraints cannot be handled by gcc. These are of the form where two operands to an insn my not be the same. The ra will only make them the same if they do not interfere, and this can only happen if one is not initialized. There is also the unfortunate consequence that this may mask some buggy programs where people forget to initialize stack variable. Any programmer with half a brain would look at the uninitialized variable warnings. */ However this seems to not touch variables with only may-uninitialized accesses. > And to initialize allocated variables with some bit pattern you can simply > override malloc. Or use MALLOC_PERTURB_ environment variable. -- Alexander
Re: C/C++ Option to Initialize Variables?
Hi, On Mon, 18 Feb 2013, Jeffrey Walton wrote: > On Mon, Feb 18, 2013 at 10:34 AM, Andrew Haley wrote: > > On 02/18/2013 03:07 PM, Jeffrey Walton wrote: > >> On Mon, Feb 18, 2013 at 9:43 AM, Jonathan Wakely > >> wrote: > >>> On 18 February 2013 13:28, Jeffrey Walton wrote: > > > What if the ".BSS" section was > initialized to 0xFF rather than a page full of NULLs? > >>> > >>> That could break millions of perfectly valid programs, for no obvious > >>> benefit. > >> Its hypothetical, and could be a bit humorous. Why are developers > >> writing programs that rely upon undocumented features? > > > > BSS being zero is certainly not an undocumented feature. > > C/C++ makes no assurances on the value of an unitialized variable, > members, etc. Wrong. It specifies that objects with static storage duration that aren't explicitely initialized are initialized with null pointers, or zeros depending on type. 6.7.8.10. Hence if .bss is to be used to place such objects then the runtime system _must_ make sure that it's zero initialized. IOW: it's only automatic and allocated variables that start with an indeterminate value when not initialized explicitely. Automatic variables, as they are on the stack, are unlikely to usually get the value 0 out of pure luck, so an option to initialize them to 0xDEADBEAF doesn't make much sense. And to initialize allocated variables with some bit pattern you can simply override malloc. So, this option seems to search for a problem it's supposed to help with. Ciao, Michael.
Re: C/C++ Option to Initialize Variables?
On Monday 18 February 2013 09:44 PM, Jeffrey Walton wrote: On Mon, Feb 18, 2013 at 10:34 AM, Andrew Haley wrote: On 02/18/2013 03:07 PM, Jeffrey Walton wrote: On Mon, Feb 18, 2013 at 9:43 AM, Jonathan Wakely wrote: On 18 February 2013 13:28, Jeffrey Walton wrote: What if the ".BSS" section was initialized to 0xFF rather than a page full of NULLs? That could break millions of perfectly valid programs, for no obvious benefit. Its hypothetical, and could be a bit humorous. Why are developers writing programs that rely upon undocumented features? BSS being zero is certainly not an undocumented feature. C/C++ makes no assurances on the value of an unitialized variable, members, etc. DATA section is initialized data. BSS section is unitialized data. For statically allocated unitintialized object, it will go in BSS section. For uninitialized stack variable, it will go on the stack. Forgive me, but I don't see where anything is guaranteed to be zero'd before use. I'm likely wrong somewhere since you disagree. http://en.wikipedia.org/wiki/.bss Uday.
Re: C/C++ Option to Initialize Variables?
On Mon, Feb 18, 2013 at 10:34 AM, Andrew Haley wrote: > On 02/18/2013 03:07 PM, Jeffrey Walton wrote: >> On Mon, Feb 18, 2013 at 9:43 AM, Jonathan Wakely >> wrote: >>> On 18 February 2013 13:28, Jeffrey Walton wrote: > What if the ".BSS" section was initialized to 0xFF rather than a page full of NULLs? >>> >>> That could break millions of perfectly valid programs, for no obvious >>> benefit. >> Its hypothetical, and could be a bit humorous. Why are developers >> writing programs that rely upon undocumented features? > > BSS being zero is certainly not an undocumented feature. C/C++ makes no assurances on the value of an unitialized variable, members, etc. DATA section is initialized data. BSS section is unitialized data. For statically allocated unitintialized object, it will go in BSS section. For uninitialized stack variable, it will go on the stack. Forgive me, but I don't see where anything is guaranteed to be zero'd before use. I'm likely wrong somewhere since you disagree. Jeff
Re: C/C++ Option to Initialize Variables?
On 02/18/2013 03:07 PM, Jeffrey Walton wrote: > On Mon, Feb 18, 2013 at 9:43 AM, Jonathan Wakely > wrote: >> On 18 February 2013 13:28, Jeffrey Walton wrote: >>> What if the ".BSS" section was >>> initialized to 0xFF rather than a page full of NULLs? >> >> That could break millions of perfectly valid programs, for no obvious >> benefit. > Its hypothetical, and could be a bit humorous. Why are developers > writing programs that rely upon undocumented features? BSS being zero is certainly not an undocumented feature. Andrew.
Re: C/C++ Option to Initialize Variables?
On Mon, Feb 18, 2013 at 9:43 AM, Jonathan Wakely wrote: > On 18 February 2013 13:28, Jeffrey Walton wrote: >> The reason I went looking for the flag is someone asked about a crash >> on the OpenSSL mailing list. I knew it was due to an uninitialized >> field (but they did not realize the value was not initialized). I >> wanted to suggest a quick way to find what was not initialized. > > Valgrind. That requires an additional package, and some developers don't use it. >> How much code do you think would break because folks depend on getting >> a 0 due to good graces or side effects (for example, the memory >> manager returning a zeroized page)? > > It should break no valid programs. The invalid programs that break > would benefit from an easily reproducable failure. Right. >> What if the ".BSS" section was >> initialized to 0xFF rather than a page full of NULLs? > > That could break millions of perfectly valid programs, for no obvious benefit. Its hypothetical, and could be a bit humorous. Why are developers writing programs that rely upon undocumented features? As crazy as it sound, it probably portable though. Are there any OS link/loaders which use a memory manager that does not serve zeroized pages (at least on the first run when drawing from a fresh pool)? It not just userland. I've looked at lots of kernel code that relies on the same good graces and luck. I'd love to see the effects of the memory manager returning a page filed with HASH(counter). >> When building for tools such as Valgrind, don't specify the flag ;) > > You don't build for valgrind, it runs normal, uninstrumented binaries. > That's one of its main advantages. Yes, agreed. The switch would *not* be specified for production code ('release' builds). But I'm talking about development ('debug' builds). Jeff
Re: C/C++ Option to Initialize Variables?
On 18 February 2013 13:28, Jeffrey Walton wrote: > The reason I went looking for the flag is someone asked about a crash > on the OpenSSL mailing list. I knew it was due to an uninitialized > field (but they did not realize the value was not initialized). I > wanted to suggest a quick way to find what was not initialized. Valgrind. > How much code do you think would break because folks depend on getting > a 0 due to good graces or side effects (for example, the memory > manager returning a zeroized page)? It should break no valid programs. The invalid programs that break would benefit from an easily reproducable failure. > What if the ".BSS" section was > initialized to 0xFF rather than a page full of NULLs? That could break millions of perfectly valid programs, for no obvious benefit. > When building for tools such as Valgrind, don't specify the flag ;) You don't build for valgrind, it runs normal, uninstrumented binaries. That's one of its main advantages.
Re: C/C++ Option to Initialize Variables?
On 02/18/2013 03:28 PM, Jeffrey Walton wrote: On Mon, Feb 18, 2013 at 7:42 AM, Michael Veksler wrote: On 02/18/2013 02:02 PM, Alec Teal wrote: On 18/02/13 11:40, Jeffrey Walton wrote: Hi All, http://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#C-Dialect-Options Is there an option to initialize variables to known values in a C/C++ program? My use case is 'debug' builds and finding use of uninitialized values that get lucky by being 0 most of the time. For example: void DoSomeithWithFoo(FOO** ppf) { if(ppf && *ppf == NULL) { *ppf = new FOO; ... } } FOO* p; DoSomeithWithFoo(&p); So I would like something that initializes to known, but non-NULL, such as 0xCDCDCDCD or 0xFDFDFDFD (similar to Visual Studio behavior). ... I believe Jeff thinks the above is a bug in *his* code, and he wants a flag to help him spot it. By assigning non-NULL values to unintialized variables will, supposedly, make the code behave wrongly, making it easier to detect. The reason I went looking for the flag is someone asked about a crash on the OpenSSL mailing list. I knew it was due to an uninitialized field (but they did not realize the value was not initialized). I wanted to suggest a quick way to find what was not initialized. How much code do you think would break because folks depend on getting a 0 due to good graces or side effects (for example, the memory manager returning a zeroized page)? What if the ".BSS" section was initialized to 0xFF rather than a page full of NULLs? I agree that having gcc deliberately put garbage into uninitialized variables can be very helpful in shortening the compile-test-debug-fix loop. I run valgrind only occasionally, even though I run unit-tests after every modification. This means that bugs due to unintialized memory are sometimes detected many days after they were first introduced, which makes it more difficult to understand the bug. Testing code compiled with this flag will probably result in less bugs of this kind left to testing by valgrind. Yes, it's a great feature of Visual Studio. It helps you find the point of first failure (or the potential point) quickly. I see the main issue with such flags in their interaction with tools like valgrind. Such a flag could defeat valgrind's algorithm for detecting unintialized local variables, unless it is made aware of the flag (which I don't see how it could be done, without special hints from gcc). When building for tools such as Valgrind, don't specify the flag ;) I like when things just work, without weird dependencies. But the trade-off sounds reasonable to me in this case, but I am not a GCC developer and have no moral right to justify this claim. Instead of joining your request for a new GCC feature I have a suggestion to you. How about writing a plug-in for GCC to do that? I am no expert, but writing a melt plug-in does not sound too complicated: http://gcc-melt.org/ It is possible that you could add an initialization to every uninitialized variable in a simple melt plug-in. I have never written a plug-in so I may be completely wrong, and it is not that simple. I think that it is worth having a look. Michael
Re: C/C++ Option to Initialize Variables?
On Mon, Feb 18, 2013 at 7:42 AM, Michael Veksler wrote: > On 02/18/2013 02:02 PM, Alec Teal wrote: >> >> On 18/02/13 11:40, Jeffrey Walton wrote: >>> >>> Hi All, >>> >>> >>> http://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#C-Dialect-Options >>> >>> Is there an option to initialize variables to known values in a C/C++ >>> program? >>> >>> My use case is 'debug' builds and finding use of uninitialized values >>> that get lucky by being 0 most of the time. For example: >>> >>> void DoSomeithWithFoo(FOO** ppf) { >>>if(ppf && *ppf == NULL) { >>> *ppf = new FOO; >>> ... >>>} >>> } >>> >>> FOO* p; >>> DoSomeithWithFoo(&p); >>> >>> So I would like something that initializes to known, but non-NULL, >>> such as 0xCDCDCDCD or 0xFDFDFDFD (similar to Visual Studio behavior). >>> >> ... >> >> > I believe Jeff thinks the above is a bug in *his* code, and he wants a flag > to > help him spot it. By assigning non-NULL values to unintialized variables > will, > supposedly, make the code behave wrongly, making it easier to detect. The reason I went looking for the flag is someone asked about a crash on the OpenSSL mailing list. I knew it was due to an uninitialized field (but they did not realize the value was not initialized). I wanted to suggest a quick way to find what was not initialized. How much code do you think would break because folks depend on getting a 0 due to good graces or side effects (for example, the memory manager returning a zeroized page)? What if the ".BSS" section was initialized to 0xFF rather than a page full of NULLs? > I agree that having gcc deliberately put garbage into uninitialized > variables can > be very helpful in shortening the compile-test-debug-fix loop. I run > valgrind only > occasionally, even though I run unit-tests after every modification. This > means > that bugs due to unintialized memory are sometimes detected many days after > they were first introduced, which makes it more difficult to understand the > bug. Testing code compiled with this flag will probably result in less bugs > of > this kind left to testing by valgrind. Yes, it's a great feature of Visual Studio. It helps you find the point of first failure (or the potential point) quickly. > I see the main issue with such flags in their interaction with tools like > valgrind. Such a flag could defeat valgrind's algorithm for detecting > unintialized local variables, unless it is made aware of the flag > (which I don't see how it could be done, without special hints from gcc). When building for tools such as Valgrind, don't specify the flag ;) Jeff
Re: C/C++ Option to Initialize Variables?
On 02/18/2013 02:02 PM, Alec Teal wrote: On 18/02/13 11:40, Jeffrey Walton wrote: Hi All, http://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#C-Dialect-Options Is there an option to initialize variables to known values in a C/C++ program? My use case is 'debug' builds and finding use of uninitialized values that get lucky by being 0 most of the time. For example: void DoSomeithWithFoo(FOO** ppf) { if(ppf && *ppf == NULL) { *ppf = new FOO; ... } } FOO* p; DoSomeithWithFoo(&p); So I would like something that initializes to known, but non-NULL, such as 0xCDCDCDCD or 0xFDFDFDFD (similar to Visual Studio behavior). Jeff Probably not, put =0, if I say "int x;" I am just saying there is an int, it's name is x, deal with it. I may assign to it later, sticking =0 at the end implicitly wouldn't be good for anything really. However! calloc initializes the memory to zero change malloc(size to calloc(1,size and you're done. Does that help? Alec I believe Jeff thinks the above is a bug in *his* code, and he wants a flag to help him spot it. By assigning non-NULL values to unintialized variables will, supposedly, make the code behave wrongly, making it easier to detect. I agree that having gcc deliberately put garbage into uninitialized variables can be very helpful in shortening the compile-test-debug-fix loop. I run valgrind only occasionally, even though I run unit-tests after every modification. This means that bugs due to unintialized memory are sometimes detected many days after they were first introduced, which makes it more difficult to understand the bug. Testing code compiled with this flag will probably result in less bugs of this kind left to testing by valgrind. I see the main issue with such flags in their interaction with tools like valgrind. Such a flag could defeat valgrind's algorithm for detecting unintialized local variables, unless it is made aware of the flag (which I don't see how it could be done, without special hints from gcc). Michael
Re: C/C++ Option to Initialize Variables?
On 18/02/13 11:40, Jeffrey Walton wrote: Hi All, http://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#C-Dialect-Options Is there an option to initialize variables to known values in a C/C++ program? My use case is 'debug' builds and finding use of uninitialized values that get lucky by being 0 most of the time. For example: void DoSomeithWithFoo(FOO** ppf) { if(ppf && *ppf == NULL) { *ppf = new FOO; ... } } FOO* p; DoSomeithWithFoo(&p); So I would like something that initializes to known, but non-NULL, such as 0xCDCDCDCD or 0xFDFDFDFD (similar to Visual Studio behavior). Jeff Probably not, put =0, if I say "int x;" I am just saying there is an int, it's name is x, deal with it. I may assign to it later, sticking =0 at the end implicitly wouldn't be good for anything really. However! calloc initializes the memory to zero change malloc(size to calloc(1,size and you're done. Does that help? Alec