6

Accidential use of classes inside of c style typeless variable arguments list is a common error source. Example:

class MyString {
    public:
    char *pChars;
    int Length;

    MyString(char *pChars) {
        this->pChars = pChars; 
        Length = strlen(pChars); 
        } };

int main() {
    MyString s1("Bla1"), s2("Bla2");
    printf("%s%s", s1, s2); // This does not but should give a compiler warning/error!
    return 0; }

The printf call there receives the two s objects by value. that means all of their members are simply memory copied. But they are interpreted a simple char pointers. Result is a runtime error of course.

I am not asking for a solution to this, but I would like to have something I could add to my class so that the compiler warns me about it or gives an error.

Already tried to declarate but not implement a copy constructor. But it seems that no copy constructor is called. :-(

Please just answer to the question in the title. I do not need a discusson of why you should not use printf or these variable arguments lists - know that.

Thanks for your time.

Ole Dittmann
  • 1,764
  • 1
  • 14
  • 22
  • "I do not need a discusson of why you should not use printf or these variable arguments lists - know that." - What is wrong with printf? – alternative Aug 16 '10 at 13:22
  • @mathepic: I can see one thing "wrong" with `printf`: it can invoke UB if you pass custom types as parameters (like in the question), while `std::stream's` can deal with them gracefully. But when properly used, there is nothing wrong with it. – ereOn Aug 16 '10 at 13:36
  • Check your compiler documentation there should be a flag to get it to warn in that case. The g++ compiler warns whenever a non-POD class is passed as arguments to a function with variable arguments. – David Rodríguez - dribeas Aug 16 '10 at 14:10

3 Answers3

11

Decent compilers (like gcc) check whether printf arguments match format specifiers in format string.

Just do not forget to add -Wformat or -Wall command line option.

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

qrdl
  • 34,062
  • 14
  • 56
  • 86
  • 4
    Well, maybe visual C++ is no descent compiler? – Ole Dittmann Aug 16 '10 at 13:44
  • 2
    @kaptnole they postponed on the decency, at least regarding the issue you're experiencing :) http://connect.microsoft.com/VisualStudio/feedback/details/98899/compiler-should-warn-about-passing-objects-of-non-pod-types-to-the-ellipsis. I know you don't want to hear this but don't use printf see advices here http://stackoverflow.com/questions/2017489/should-i-use-printf-in-my-c-code – celavek Aug 16 '10 at 14:18
  • @celavek I would have accepted your comment as an answer if you would have posted it as one :-) – Ole Dittmann Sep 09 '10 at 11:23
  • @kaptnole well ... tough luck :) – celavek Sep 09 '10 at 11:37
0

Derive from boost::noncopyable

Sebastian
  • 4,802
  • 23
  • 48
  • 1
    That's equivalent to Cătălin's answer, and has the same problem; it won't prevent passing through `...`, since that gives undefined behaviour, not a copy. – Mike Seymour Aug 16 '10 at 14:43
0

Hide copy constructor and assignment operator (declare them private, no need to implement them). Or derive the class from boost::noncopyable (which has the same effect).Passing arguments by value determines the usage of the copy constructor.

Cătălin Pitiș
  • 14,123
  • 2
  • 39
  • 62
  • 2
    Except this doesn't help because the instance is not passed by value, but rather some raw bytes are passed and then `reinterpret_cast` -ed to `const char*`. I don't think there is a language-level means to avoid the situation. You can only depend on the compiler warning (e.g "cannot pass non-POD object through ...") – visitor Aug 16 '10 at 13:46
  • 1
    Well the OP said in his question already that he played with the copy constructor. Do you think that also overloading the assignment operator will change the behavior? Is that a feature/bug of visual c++? – Jens Gustedt Aug 16 '10 at 14:21