Does -DNDEBUG intefere with -g flag? - c

I had two questions regarding the -DNDEBUG that I didnt quite understand after doing some reading on it.
1) Will it cause problems if both -DNDEBUG and -g flags are used together?
2) Does the -DNDEBUG flag turn off asserts? (This means that asserts wont work)

To expand #kaylum's valid answer.
-DNDEBUG consists of two parts, the flag -D and the argument NDEBUG. The flag is used to create preprocessor defines, therefore this will create a new preprocessor #define called NDEBUG
-g is a compiler switch to generate debugging information. It works completely separate from creating defines with -D. Read more about debugging flags here.

Related

gcc linking object files with warning/optimization flags

We are compiling a piece of software using generics where files are first made into object files, they are built like so:
arm-unknown-linux-gnu-gcc -c -O2 -Wstrict-prototypes -Wdeclaration-after-statement -fsigned-char -I/opt/tm-sdk/include -mlittle-endian -Wno-trigraphs -fno-strict-aliasing -fno-omit-frame-pointer -march=armv4 -mtune=arm9tdmi -Wall -Wextra -o src/flex.o src/flex.c
...
arm-unknown-linux-gnu-gcc -c -O2 -Wstrict-prototypes -Wdeclaration-after-statement -fsigned-char -I/opt/tm-sdk/include -mlittle-endian -Wno-trigraphs -fno-strict-aliasing -fno-omit-frame-pointer -march=armv4 -mtune=arm9tdmi -Wall -Wextra -o src/flexdb.o src/flexdb.c
Then they are linked with:
arm-unknown-linux-gnu-gcc -o flex src/flex.o src/flexdb.o src/flexio.o src/flexprotocol.o src/flexsettings.o src/flexstate.o -L/opt/tm-sdk/lib -ltag -lrt -ltmreader -lsqlite3 -lsha1
My questions is:
Do we need to include optimization and warning flags during linking? Would it do anything if -Wall, -Wextra, and -O2 were included when creating the flex binary from the object files?
Edit: Clarifying meaning based on feedback.
Do we need to include optimization and warning flags during this final stage of compilation?
Of course you don't need to include them for the link stage. You already know that, because you don't include them. But I think what you really want to know is ...
Would it do anything if -Wall, -Wextra, and -O2 were included when building the flex binary from object files.
All or almost all warnings are generated during the compilation stage. I don't off-hand know any exceptions, but it's conceivable that there are some. Thus, it's possible that passing warning-related flags during linking would trigger warnings that otherwise you would not receive. But that shouldn't affect the compiled binary in any way.
Optimization is different. There are optimizations that can be performed at link time, but that might not be performed at the default optimization level. Omitting optimization flags from the link command should not break your build, but including them may result in a binary that is faster and / or smaller.
Overall, I see no good reason to avoid passing the same warning and optimization flags during the link step that you do during the compilation steps. If you wish, it's not harmful to pass preprocessor-specific flags (e.g. -D) as well, as they'll just be ignored during linking. I presume that all this is managed by make, so it's not like you actually need to type out the options every time.
NO You're just calling the linker with the final call to gcc and -W and -O flags are for the compiler.
-Wall is primarily a preprocessor option, but there is also a reference for the libraries. See here
-Wextra appears to be strictly a c++ preprocessor option. See here
-O2 is a compiler optimization level setting. See here
So to answer your precise question, only -Wall would possibly help during your link step. The other two would not. You could test this by building with and without these options, seeing if any additional output is created in the case of warnings and if the code size or execution time differed between builds.

Building a trivial program with dpkg-buildflags

I'm trying to build a very simple C program for inclusion into a .deb package. The bulk of the project is in Python. When this program is included into a .deb package, lintian gives me the hardening-no-fortify-functions warning.
On further reading, it appears that Debian expects you to include certain flags while building C programs, and that these flags can be retrieved using dpkg-buildflags --get CFLAGS.
My initial build flags looked like this:
gcc -Wall -pedantic -o somefile somefile.c
Now, I'm building with
CFLAGS=`dpkg-buildflags --get CFLAGS`
gcc $CFLAGS -o somefile somefile.c
However, I continue to get the hardening-no-fortify-functions warning. What am I doing wrong here? Is this now a false positive? Can I just add an override and forget about it?
There are several possibilities of which the third seems most likely, but I've mentioned 1 and 2 in case they are causing you problems too:
dpkg-buildflags --get CFLAGS is returning the wrong thing. On my system it returns:
-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -Werror=format-security
If you just execute it from the command line, what do you get?
Your value of CFLAGS is not being passed to gcc. I assume you are using a Makefile here; are those two statements actually adjacent? Do you not want CFLAGS = (with a space) if so? Or are you setting CFLAGS at the command line in which case you should know the debian build tool stuff strips the environment of most things that don't start DEB_, so you will need to set CFLAGS inside whatever builds the package.
The CFLAGS aren't sufficient to eliminate the hardening error. Let's have a look at the lintian error: http://lintian.debian.org/tags/hardening-no-fortify-functions.html and note it says 'Certainty: wild guess'. That does not inspire confidence that it is correct. However, I suspect the actual problem is this: you are not bringing in LDFLAGS. Try:
$ dpkg-buildflags --get LDFLAGS
-Wl,-Bsymbolic-functions -Wl,-z,relro
You'll need those on your linker line.
This approach would seem to work (i.e. at least compile):
gcc `dpkg-buildflags --get CFLAGS` `dpkg-buildflags --get LDFLAGS` main.c -o main

Compiler flags when setting debug and release mode

gcc (GCC) 4.7.2
cmake version 2.8.10.2
c89
I am using cmake as my build system. And I want to set the flags accordingly to either debug or release.
Compile with debug
SET(CMAKE_C_FLAGS_DEBUG "-Wall -Wextra -Wunreachable-code -g -m32 -D_DEBUG -O0 -D_LARGEFILE64_SOURCE -D_REETRANT -D_THREAD_SAFE")
Compile with release
SET(CMAKE_C_FLAGS_RELEASE "-Wall -Wextra -Wunreachable-code -m32 -DNDEBUG -O2 -D_LARGEFILE64_SOURCE -D_REETRANT -D_THREAD_SAFE")
For the debug I have included the flags -g and set optimization to level 0.
For the release I have removed flags -g and add the N for -DNDEBUG, -DNREETRANT, and -DNTHREAD_SAFE and set the optimization to level 2.
I am right in saying that the N means NO DEBUG?
Is this all I would need to do to distinguish between a debug and release build?
Here is some recommendations based on your CMake flags:
Debug mode -g -O0, and release mode -O2 -g . It is better to add the -g flag even for O2 release mode if the code size is not critical. With -g, some symbol information of the code is included, it only increase the whole binary size by about 10%~ 20%, but users can help give you a stack dump, which can help a lot for debug.
Use -UDEBUG -UREETRANT instead of -DNDEBUG -DNREETRANT. The -DMACRO flag is just like add #define MACOR in your code, and if you have code region like #ifdef MACRO SOME_DEBUG_CODE #endif, the preprocessor will keep the code there, while -UDEBUG flag is like #undefine MACRO, and the preprocessor will delete the SOME_DEBUG_CODE. If you just add -DNDEBUG -DNREETRANT, it is like add#define NDEBUG #defin NREETRANT in your code, which is meaningless.
What would you need -D_DEBUG for if you could just as well check for the absence of NDEBUG? (Unless, of course, you want seperate control over assert and other debugging #ifdef's. I never had that need.)
Why would you want different settings for reentrancy and thread safety?
Bottom line, what you want different between Debug and Release code is completely up to you. I want my debug code to include coverage information, and my release code to be -O3. Your mileage obviously varies. Neither way is "right" or "wrong".
You might also want to note that:
CMake sets stuff like -g -O0 and -O2 automatically, so it would be sufficient to append the desired warnings and additional flags.
You might want to keep an eye on portability and check for if ( CMAKE_COMPILER_IS_GNUC ) (or ..._GNUCC for C++) before you set the compiler flags.
As Ling Kun said, you can keep -g even in Release code. At least during development it is useful, and you can command CMake to strip executables during installation. (Personally, I strive for not having to make my customers extract post-mortem stack / core dumps. ;-) )

Where to add a CFLAG, such as -std=gnu99, into an autotools project

I have a simple Autotools C project (not C++).
CFLAGs (by inspection) seem to be -g -O2.
I want all of the generated make files to also have -std=gnu99 appended to the CFLAGs, because I use for (int i = 0; i < MAX; i++) and similar.
I can obviously hack the Makefile, but this gets overwritten on ./configure.
Where is the correct place to add (or change) CFLAGs which are required by the code (as opposed to those CFLAGs which the user might want to change)?
(Note this is partial duplicate of Where to add a CFLAG, such as -std=gnu99, into an (Eclipse CDT) autotools project as I was getting Eclipse-specific answers which I didn't want.)
#DevSolar's answer has not helped yet. A configure.ac file (below) generates the configure script (also below).
configure.ac:
dnl Process this file with autoconf to produce a configure script.
CFLAGS="$CFLAGS -std=gnu99"
AC_PREREQ(2.59)
AC_INIT(tuntest, 1.0)
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE()
AC_PROG_CC
AC_CONFIG_FILES(Makefile src/Makefile)
AC_OUTPUT
$ grep CFLAGS configure
CFLAGS
CFLAGS
To assign environment variables (e.g., CC, CFLAGS...), specify them as
CFLAGS C compiler flags
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_test_CFLAGS=${CFLAGS+set}
ac_save_CFLAGS=$CFLAGS
CFLAGS="-g"
CFLAGS=""
CFLAGS="-g"
if test "$ac_test_CFLAGS" = set; then
CFLAGS=$ac_save_CFLAGS
CFLAGS="-g -O2"
CFLAGS="-g"
CFLAGS="-O2"
CFLAGS=
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
autoconf has a macro for this:
Just put:
AC_PROG_CC_STDC
after your AC_PROG_CC and everything will be right.
Especially when you use other compilers that do not have -std=gnu99 but operate in C99 mode by default (or have a different option hpcc's -AC99 springs to mind).
I would NOT use CFLAGS for that kind of thing.
From the docs:
-- Macro: AC_PROG_CC_STDC
If the C compiler cannot compile ISO Standard C (currently C99),
try to add an option to output variable `CC' to make it work. If
the compiler does not support C99, fall back to supporting ANSI
C89 (ISO C90).
After calling this macro you can check whether the C compiler has
been set to accept Standard C; if not, the shell variable
`ac_cv_prog_cc_stdc' is set to `no'.
Although using a macro like AC_PROG_CC_STDC is preferable to adding compiler options to CFLAGS, autoconf currently has no macros enabling C11 compiler support -- there is no AC_PROG_CC_C11 yet, and AC_PROG_CC_STDC only adds the -std=gnu99 option for gcc instead of -std=gnu11 or -std=c11.
You can add compiler flags simply by putting
CFLAGS="$CFLAGS -std=c11"
in the configure.ac.
Alternatively, it might be better to check first if the compiler supports the added option, and print a warning otherwise, telling the user to manually add an equivalent option to CFLAGS that works for their compiler:
AX_CHECK_COMPILE_FLAG([-std=c11],
[AX_APPEND_FLAG([-std=c11])],
[AC_MSG_WARN([-std=c11 not supported, you may have to set CFLAGS to enable C11 support.])
])
This uses the AX_CHECK_COMPILE_FLAG and AX_APPEND_FLAG macros found in the GNU Autoconf Archive. To use them, put them into an m4 subdirectory and add AC_CONFIG_MACRO_DIR([m4]) to configure.ac
This topic is covered in the Automake manual, 27.6 Flag Variables Ordering. There an interaction between configure.ac and Makefile.am, and its more than just setting a well known shell variable used in implicit make rules.
The short of it is, you should set it in a new variable called something like mumble_CFLAGS discussed in the Automake manual. mumble is just the name of your program, and it is often foo or bar in other examples. Later, when your makefile is created, the recipe for your program (mumble or foo or bar) will use $(mumble_CFLAGS) $(CFLAGS) to build the target.
Here is an example of how it might look. Instead of using mumble or foo or bar, it uses my_prog as a artifact name.
configure.ac:
# Perform a compile test using -std=gnu99, set has_gnu99
if test "$has_gnu99" -eq "1"; then
AC_SUBST([MY_GNU99], [-std=gnu99])
fi
Makefile.am:
bin_PROGRAMS = my_prog
my_prog_CFLAGS = $(MY_GNU99) $(MY_ANOTHER_FLAG) $(MY_YET_ANOTHER_FLAG) ...
Later, when the makefile is generated, it will have a recipe similar to the following, where $(MY_PROG_CFLAGS) is applied to all the objects that build my_prog:
my_prog :
$(CC) $(CPPFLAGS) $(MY_PROG_CFLAGS) $(CFLAGS) -c $< -o $#
The extra indirections of my_prog_CFLAGS allows you to have multiple flags for different targets. For example, you could have a my_prog_CFLAGS, a my_archive_CFLAGS and a my_sharedobj_CFLAGS.
And its not limited to my_prog_CFLAGS. You could also have my_prog_CPPFLAGS, my_prog_CXXFLAGS and other variables used implicitly in makefiles.
This is from the Automake manual:
Compile Flag Variables
This section attempts to answer all the above questions. We will
mostly discuss CPPFLAGS in our examples, but actually the answer holds
for all the compile flags used in Automake: CCASFLAGS, CFLAGS,
CPPFLAGS, CXXFLAGS, FCFLAGS, FFLAGS, GCJFLAGS, LDFLAGS, LFLAGS,
LIBTOOLFLAGS, OBJCFLAGS, OBJCXXFLAGS, RFLAGS, UPCFLAGS, and YFLAGS.
CPPFLAGS, AM_CPPFLAGS, and mumble_CPPFLAGS are three variables that
can be used to pass flags to the C preprocessor (actually these
variables are also used for other languages like C++ or preprocessed
Fortran). CPPFLAGS is the user variable (see User Variables),
AM_CPPFLAGS is the Automake variable, and mumble_CPPFLAGS is the
variable specific to the mumble target (we call this a per-target
variable, see Program and Library Variables).
Automake always uses two of these variables when compiling C sources
files. When compiling an object file for the mumble target, the first
variable will be mumble_CPPFLAGS if it is defined, or AM_CPPFLAGS
otherwise. The second variable is always CPPFLAGS.
In the following example,
bin_PROGRAMS = foo bar
foo_SOURCES = xyz.c
bar_SOURCES = main.c
foo_CPPFLAGS = -DFOO
AM_CPPFLAGS = -DBAZ
xyz.o will be compiled with ‘$(foo_CPPFLAGS) $(CPPFLAGS)’, (because
xyz.o is part of the foo target), while main.o will be compiled with
‘$(AM_CPPFLAGS) $(CPPFLAGS)’ (because there is no per-target variable
for target bar).
The difference between mumble_CPPFLAGS and AM_CPPFLAGS being clear
enough, let’s focus on CPPFLAGS. CPPFLAGS is a user variable, i.e., a
variable that users are entitled to modify in order to compile the
package. This variable, like many others, is documented at the end of
the output of ‘configure --help’.
For instance, someone who needs to add /home/my/usr/include to the C
compiler’s search path would configure a package with
./configure CPPFLAGS='-I /home/my/usr/include'
and this flag would be propagated to the compile rules of all
Makefiles.

C gcc compilation question and makefiles

Not even quite sure what my question is. The short of it is, for a class I'm supposed to add some functionality to this c file, and it came with a handy makefile.
CFLAGS=-DUNIX -lreadline -lcurses -ansi -pedantic-errors
DEBUG=-g
#DEBUG=
all: shell
shell: shell.c parse.c parse.h
gcc $(CFLAGS) $(DEBUG) shell.c parse.c -o shell
clean:
rm -f shell *~
I have to add features to shell.c. I'm very new to C (usually use c++ or c#) so I'm testing out little things in a separate little tests.c file. Things like, see what exactly certain system calls return, how to printf them right, etc. Anyway, tests.c seems to be conforming to different c compiler standards or I'm compiling it wrong. If I accidentally use // to comment something out or declare a variable somewhere other than at the start in shell.c, the compiler yells at me. It doesn't care in tests.c.
I compile tests.c with "gcc tests.c -o tests"
If I compile the shell using "gcc shell.c parse.c -o shell" it compiles fine, but running it simply gives me a segmentation fault. I would love to ask my TA about this, but every time I as him something he answers a completely different question...
Any thoughts on what's going on here? Perhaps a point in the right direction at least?
The problem is that your makefile includes -ansi -pedantic-errors flags for the compiler. This forces it to use a very old version of C. Perhaps this Makefile was provided by your instructor and he wants like that? It is not uncommon.
To use these new features (// comments, automatic variables anywhere in a block) just drop these two flags. If you have the freedom, I recommend also using -std=c99 -Wall.
To get GCC to accept C99 conventions, tell it to do so:
gcc -std=c99 ...
gcc -std=gnu99 ...
So, add -std=gnu99 to your CFLAGS value, and remove -ansi which is equivalent to -std=c89. If you must code to C89 standards, do not use // comments.
We can't tell what causes the core dump - but it could be that you're trying to modify a string literal somewhere, or any of a large number of other problems.
The -ansi -pedantic-errors prevents the impurities like // and variable definitions in the middle of the function. Remove that and you should be able to sin away.
As for the segmentation fault, your best bet is to run your program through gdb to see where it crashes.
Why are you compiling by calling gcc directly instead of using the makefile? The makefile adds a number of additional command-line gcc options which are most likely important. Do you see the same behavior if you compile using make all?
Since you are new to C, I would recommend adding -Wall to the CFLAGS line. This will enable all compiler warnings, which may alert you to a subtle error that you might have otherwise missed.

Resources