-1

What is wrong with this code?

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

void myprintf(const char * format, ...) __printflike(1, 2);

int main(int argc, const char * argv[]) {
    printf("%s\n");
    myprintf("%s\n");
    return 0;
}

void myprintf(const char * format, ...) {
    if (format) {
        va_list arguments;
        va_start(arguments, format);
        vprintf(format, arguments);
        va_end(arguments);
    }
}

By using __printflike I get a nice warning, like printf. But unlike printf, which prints trash at least, I get EXC_BAD_ACCESS on the call to vprintf as shown here:

enter image description here

Is there any way I can make this work? Thanks!

UPDATE: I understand that by calling a function with the wrong number of arguments I get undefined behavior, but I'd like myprintf to behave just like printf does (without crashing). Is that possible? Is there any way I can check the arguments before calling vprintf to avoid the exception?

UPDATE 2: I think I got it now, thanks for all the comments and answers. For this very simple example I think is better to use a macro, which fails fast and crashes at the calling point:

enter image description here

cromandini
  • 1,222
  • 1
  • 13
  • 19
  • "printf, which prints trash at least". That's not guaranteed behaviour. When you deliberately put bugs in your code that have Undefined Behaviour you cannot expect it to "print trash at least". UB means the behaviour is unpredictable. It can crash immediately, it can crash later, it can print trash, it can print nothing,... – kaylum Nov 19 '16 at 05:43
  • 1
    [Does “Undefined Behavior” really permit *anything* to happen?](http://stackoverflow.com/questions/32132574/does-undefined-behavior-really-permit-anything-to-happen) – kaylum Nov 19 '16 at 05:45
  • @kaylum I updated my question, because I'd like to know if there is a way that my function can behave like `printf`, in its undefined way. From your point of view...Documenting that behavior is undefined if the caller passes wrong arguments would be enough? Thanks! – cromandini Nov 19 '16 at 06:19
  • 2
    You are much better off with your program crashing than with it continuing. You need your program to crash. It is erroneous. If it crashes, it won't do any more damage. If it continues, who knows what damage it will do. You're seeking a pointless and undesirable objective — and one that cannot be achieved because you cannot force undefined behaviour to behave in any particular manner. See also [Fail Fast](http://www.martinfowler.com/ieeeSoftware/failFast.pdf). – Jonathan Leffler Nov 19 '16 at 06:32

3 Answers3

1

Undefined means unpredictable. In one run printf may produce trash, in another it may produce EXC_BAD_ACCESS instead. You cannot reproduce undefined behavior. In this particular case, the %s term in the formatting string says printf need to find a C-string. Depending on your libc implementation, when you did not specify the second argument, it may find it somewhere. And if it happens that a null character is found not far away from this pointer, you get trash output. If not, printf will continue to search the end of the string until it gets out of range of the memory assigned to your program and you get the EXC_BAD_ACCESS.

Yan Zhou
  • 2,709
  • 2
  • 22
  • 37
0

It is not possible - at least not in a portable way - to determine how many arguments are passed to a function. The format specifier is the only way for printf to determine how many values are to be popped from the stack so entering a wrong format specifier gives you undefined behavior. It is just one of those C things you need to learn and then move on.

By trying to "correct" something like this you may just make the code more unreadable and hard for other people to understand.

AndersK
  • 35,813
  • 6
  • 60
  • 86
0

Is there any way I can check the arguments before calling vprintf to avoid the exception?

Just one: Take the compiler's warning serious and eliminate your programming bug that the warning points you to.

See: It's becoming winter now, it will have mud and snow on the streets (in Europe at least), so you have your preferred garage mount the winter tires to your Porsche. On return of this nice car you find the following sticker on the dashboard (put there by the garage):

enter image description here

(apx 100 miles/h)

This sticker reminds you, that the freshly mounted winter tires do not support the maximum speed of the car.

You wouldn't drive faster now expecting the car to stop the moment the tires are about to break, won't you?

It's up to you, the driver to respect this warning!

;-)

alk
  • 69,737
  • 10
  • 105
  • 255