You are not logged in.

#1 2013-10-02 14:48:44

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

[SOLVED] What exactly does gcc's -Os do with the code?

Hey all,

The application that sets my statusbar in DWM, written in C, recently starting segfaulting after I changed the code (commit). I initially traced it down to being that I specify -Os to gcc in the Makefile (without that, it runs fine) and then I traced it to the perc variable in get_battery. If I stop sprintf'ing that into buf, it also doesn't segfault.

This made me start digging through the gcc documentation and now I'm stuck with two questions:
1. What does -Os do exactly with my code? I.e., does it only reduce the size of the binary (how?) or does it also do some optimization as -O1/2/3?
2. Is another optimizer (-O3) "better" than -Os? The code runs fine with this, for example.

Thanks in advance for your insights!

Last edited by Unia (2013-10-12 20:35:05)


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#2 2013-10-02 14:59:10

karol
Archivist
Registered: 2009-05-06
Posts: 25,440

Re: [SOLVED] What exactly does gcc's -Os do with the code?

http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

-O3
    Optimize yet more. -O3 turns on all optimizations specified by -O2 and also turns on the -finline-functions, -funswitch-loops, -fpredictive-commoning, -fgcse-after-reload, -ftree-loop-vectorize, -ftree-slp-vectorize, -fvect-cost-model, -ftree-partial-pre and -fipa-cp-clone options.

-Os
    Optimize for size. -Os enables all -O2 optimizations that do not typically increase code size. It also performs further optimizations designed to reduce code size.

    -Os disables the following optimization flags:

              -falign-functions  -falign-jumps  -falign-loops
              -falign-labels  -freorder-blocks  -freorder-blocks-and-partition
              -fprefetch-loop-arrays

Offline

#3 2013-10-02 15:20:55

hiciu
Member
Registered: 2010-08-11
Posts: 84

Re: [SOLVED] What exactly does gcc's -Os do with the code?

This could just be bug. Build your software with "-Os -g", run it with "gdb ./dwmst", start it with "r" ("r, enter") and wait for it to segfault. When it does collect stacktrace with "bt" ("bt, enter") and maybe check value of perc if it segfaults somewhere in that frame ("print perc").

You can also use tool like valgrind or electricfence (example) to debug this.

Offline

#4 2013-10-02 15:34:32

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,521
Website

Re: [SOLVED] What exactly does gcc's -Os do with the code?

As for the source of that, if it was one of my makefiles, just get rid of it.  I had it there for very ignorant reasons.

There still is a mystery as to why it could lead to a segfault; it shouldn't.  But there is no reason to include it.  In general, I'd (now) say that Makefiles shouldn't try to set such flags.  Just use a "CGLAFS += ..." notation so it inherets the users chosen compiler settings.

Last edited by Trilby (2013-10-02 15:35:35)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#5 2013-10-02 15:46:20

jdarnold
Member
From: Medford MA USA
Registered: 2009-12-15
Posts: 485
Website

Re: [SOLVED] What exactly does gcc's -Os do with the code?

Optimizers can do some funky things with your code. To optimize for space vs. optimize for speed just mean it will create the assembly code in different ways. These days, optimizing for size makes very little sense. Optimizing for speed can help, but it depends on a vast array of things.

Yes, I have had cases where -O flags break my code, although it seems more likely that it is exposing a bug in your code, like a dangling pointer or uninitialized memory. Do you compile with -Wall and -Wextra and clear up all the warnings?

Offline

#6 2013-10-02 21:29:17

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] What exactly does gcc's -Os do with the code?

@Karol: yes, I read that, but it doesn't really clarify (to me at least) what it does with the code or why this could cause a segfault.

@Hiciu: Here is the output:

Starting program: /home/jente/projecten/dwmst/./dwmst 
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7ffff7ffa000
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff75c2320 in XChangeProperty () from /usr/lib/libX11.so.6
(gdb) bt
#0  0x00007ffff75c2320 in XChangeProperty () from /usr/lib/libX11.so.6
#1  0x00007ffff75df584 in XStoreName () from /usr/lib/libX11.so.6
#2  0x000000000040133b in ?? ()
#3  0x00007ffff6658bc5 in __libc_start_main () from /usr/lib/libc.so.6
#4  0x00000000004013a5 in ?? ()
(gdb) print perc
No symbol table is loaded.  Use the "file" command.

It doesn't seem to be segfaulting with perc, but rather in my call to XStoreName... strange. Especially strange because before I restructured my code, it never segfaulted with -Os. I will double check my commit to see if I changed something...

@Trilby: Indeed I think it's there from when I forked this from you - at least, I don't remember adding it myself. I'm also questioning now why one would have that, if it doesn't optimize the program anyway.

@jdarnold: Yes, I compile my code with both -Wall and -Wextra. Here are all the options I pass to gcc in the Makefile:

CFLAGS   =  -Os -pedantic -Wall -Wextra -Wno-format-zero-length

Those -Wno-format-zero-length I added just to supress warnings about sprintf'ing an empty string into buf, when for example I have no music player running.

---

I guess I will just remove -Os, but I'm still curious as to why it is causing a segfault.


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#7 2013-10-02 21:39:27

falconindy
Developer
From: New York, USA
Registered: 2009-10-22
Posts: 4,111
Website

Re: [SOLVED] What exactly does gcc's -Os do with the code?

I'm still curious as to why it is causing a segfault.

You appear to have undefined behavior as a result of using uninitialized values. The extra optimizations merely expose bugs when making certain assumptions about your code. I'd expect that your code would crash when compiled with -O2 and -O3 optimizations as well.

Offline

#8 2013-10-02 21:52:55

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] What exactly does gcc's -Os do with the code?

It runs fine with -O3 and -O2, -O3 is what I'm using right now. My variable perc was indeed uninitialized, but even when I initialize it to zero I get the segfault with -Os.


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#9 2013-10-02 22:02:50

SahibBommelig
Member
From: Germany
Registered: 2010-05-28
Posts: 80

Re: [SOLVED] What exactly does gcc's -Os do with the code?

Just a quick guess from your code:

               char status[201];
               /* ... */
               sprintf(status, "%s      %s      %s      %s      %s", music, skype, net, volume, battery);
   	       XStoreName(dpy, root, status);

It would be understandable if there's a crash in XStoreName since you don't protect against buffer overflows in sprintf(). Use snprintf(). (that's an good idea even if that's not the cause).
Lower Optimization levels might not expose this since "status" might have been initialized to 0 "implicitly" (or just might have contained some null bytes by chance).

Edit:

You even changed something that might have triggered it in the linked commit:

-    sprintf(status, "%s %s %s %s %s", music, skype, net, volume, battery);
+   sprintf(status, "%s      %s      %s      %s      %s", music, skype, net, volume, battery);

Last edited by SahibBommelig (2013-10-02 22:06:18)

Offline

#10 2013-10-02 22:07:55

falconindy
Developer
From: New York, USA
Registered: 2009-10-22
Posts: 4,111
Website

Re: [SOLVED] What exactly does gcc's -Os do with the code?

Unia wrote:

It runs fine with -O3 and -O2, -O3 is what I'm using right now. My variable perc was indeed uninitialized, but even when I initialize it to zero I get the segfault with -Os.

Your analysis and what I infer from the backtrace you posted do not align. You need to initialize the char arrays in main(). If get_battery() can't access the battery file and returns without doing anything, then the value of "battery" is indeterminate when you pass it to sprintf. sprintf will then write an undetermined number of bytes into a fixed size buffer (this also means you have a potential buffer overflow as well). Your backtrace shows XStoreName -> XChangeProperty as the "cause" because you've passed a pointer to an array which might not contain a zero-byte somewhere within its own memory, and these functions assume that it exists.

Offline

#11 2013-10-03 09:54:53

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] What exactly does gcc's -Os do with the code?

Thanks Sahib and Falconindy, I will look into that this weekend!


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#12 2013-10-12 20:33:24

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] What exactly does gcc's -Os do with the code?

I was busier than expected, so I only looked into it now. It appears to have been fixed, now that I payed more attention to using snprintf et all. Thanks a bunch everyone!


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

Board footer

Powered by FluxBB