5

I'm making a embedded linux project and I want to do a simple debug messages library where I can disable my debug messages (using pre-compilation directives) when my code is in production phase and substitute for some type of log in a database (in the future). I'm having trouble with reimplementation of printf() because of va_list. This is my code until now:

My source file:

#include "debug_msgs.h"

#define ENABLE_DEBUG_MSGS   1U

#if ENABLE_DEBUG_MSGS

int print(const char *fmt, ...) {
    int n = -1;
    va_list ap;
    va_start(ap, fmt);
    n = printf(fmt, ap);
    va_end(ap);
    return n;
}

#else

int print(const char *fmt, ...) {
    return 0;
}

#endif

My header file:

#ifndef DEBUG_MSGS_H
#define DEBUG_MSGS_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdint.h>
#include <unistd.h>

int print(const char *fmt, ...);

#endif

My problem is: My implementation compiles (I know this doesn't mean nothing), but when I do a simple test like:

int num1 = 10;
int num2 = 100;
int num3 = 1000;
float floating = 3.14;
char str[] = {"Please work, please"};
int number=-1;
number = print("\nTesting %d %d %d %f %s\n", num1, num2, num3, floating, str);
printf("\nnumber = %d\n",number); //Just to check the return

I get this output:

Testing -1095005212 100 -1095005212 -0.000002 H*� 

number = 52

Complementary informations:

This is my platform info: Linux mdm9607 3.18.44 #1 PREEMPT Tue Sep 13 19:45:33 UTC 2022 armv7l GNU/Linux

My compiler info: arm-oe-linux-gnueabi-gcc

My $CFLAGS: -O2 -fexpensive-optimizations -frename-registers -fomit-frame-pointer -MMD -MP

My $LDFLAGS:

-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed

LDFLAGS += -lumdp -lumdpcommon
LDFLAGS += -lpthread -lxml2 -lrt
LDFLAGS += -lm
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Lincoln
  • 53
  • 6
  • 1
    You may want to use CPP macros instead of [or in conjunction with] a debug function. That's because if you have a call such as: `debug_print("%d\n",calculate_a_lot());` You have to call `calculate_a_lot` even if `debug_print` is a NOP. See my answer: [Distributed Computing with PThread Not Working](https://stackoverflow.com/a/68091540/5382650) for use of the debug macro along with the debug function. – Craig Estey Sep 28 '22 at 14:06
  • 1
    You may want to turn on more compiler warnings, I'm surprised the version in your post compiled. – CoffeeTableEspresso Sep 28 '22 at 14:58
  • @CoffeeTableEspresso Good point, what other compiler warnings would you suggest-me? – Lincoln Sep 28 '22 at 16:21
  • 1
    `-Wall` (turns on a lot of warnings) and `-Werror` (turn warnings into errors) are two good flags to add. Later, if you find that `-Wall` gives you any warnings you don't want, you can turn _just that specific warning_ off. – CoffeeTableEspresso Sep 28 '22 at 16:53

1 Answers1

10

Instead of printf, you should be using vprintf or vfprintf with a va_list argument:

#include <stdarg.h>
#include <stdio.h>

int print(const char *fmt, ...) {
    int n;
    va_list ap;
    va_start(ap, fmt);
    n = vprintf(fmt, ap);
    va_end(ap);
    return n;
}

The erroneous code compiles because printf, as a vararg function, can accept any argument types after the format string. Yet you can avoid type mismatches for printf arguments by enabling more compiler warnings: gcc -Wall -Wextra -Werror would at least complain about using printf with a non constant format string and would perform compile time type checking if the format string is a string literal.

chqrlie
  • 131,814
  • 10
  • 121
  • 189