Search code examples
cdebuggingmakefilecompiler-flags

Debugging using makefile flags in C


I need to set up a way to debug my program from the make file. Specifically, when I type make -B FLAG=-DNDEBUG I need the program to run normally. But when this flag is not present I need a few assert() commands throughout the code to run.

To clarify I need to know how to check if this flag is not present from within my C code, I'd assume it has something to do with #ifndef, I just don't know where to go from there.

Forgive my ignorance, any response would be greatly appreciated!


Solution

  • Assuming you are talking about the assert macro from the standard library (#defined in <assert.h>) then you don't have to do anything. The library already takes care of the NDEBUG flag.

    If you want to make your own code do things only if the macro is / is not #defined, use an #ifdef as you already suspect in your question.

    For example, we might have a condition that is too complex to put into a single assert expression so we want a variable for it. But if the assert expands to nothing, then we don't want that value computed. So we might use something like this.

    int
    questionable(const int * numbers, size_t length)
    {
    #ifndef NDEBUG
      /* Assert that the numbers are not all the same. */
      int min = INT_MAX;
      int max = INT_MIN;
      size_t i;
      for (i = 0; i < length; ++i)
        {
          if (numbers[i] < min)
            min = numbers[i];
          if (numbers[i] > max)
            max = numbers[i];
        }
      assert(length >= 2);
      assert(max > min);
    #endif
      /* Now do what you're supposed to do with the numbers... */
      return 0;
    }
    

    Be warned that this coding style makes for hard to read code and is asking for Heisenbugs that are extremely difficult to debug. A much better way to express this is to use functions.

    /* 1st helper function */
    static int
    minimum(const int * numbers, size_t length)
    {
      int min = INT_MAX;
      size_t i;
      for (i = 0; i < length; ++i)
        {
          if (numbers[i] < min)
            min = numbers[i];
        }
      return min;
    }
    
    /* 2nd helper function */
    static int
    maximum(const int * numbers, size_t length)
    {
      int max = INT_MIN;
      size_t i;
      for (i = 0; i < length; ++i)
        {
          if (numbers[i] > max)
            max = numbers[i];
        }
      return max;
    }
    
    /* your actual function */
    int
    better(const int * numbers, int length)
    {
      /* no nasty `#ifdef`s */
      assert(length >= 2);
      assert(minimum(numbers, length) < maximum(numbers, length));
      /* Now do what you're supposed to do with the numbers... */
      return 0;
    }