0

Possible Duplicate:
What is The Rule of Three?

The following code outputs garbage at best or crashes:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class C {
public:
    char* s;
    C(char* s_) {
        s=(char *)calloc(strlen(s_)+1,1);
        strcpy(s,s_);
    };
    ~C() {
        free(s);
    };
};

void func(C c) {};

void main() {
    C o="hello";
    printf("hello: %s\n",o.s);  // works ok
    func(o);
    printf("hello: %s\n",o.s);  // outputs garbage
};

I really wonder why - the object should not even be touched because Im passing it by value ...

Community
  • 1
  • 1
Sebastian
  • 178
  • 1
  • 7
  • 4
    Also, ***PLEASE***, refrain from coding "C with Classes"... PLEASE! – Xeo Mar 09 '12 at 15:16
  • @James: Because it's everything that is bad in this (the C++) world. – Xeo Mar 09 '12 at 15:20
  • 1
    @Xeo Why force your opinion down his throat? Some people like to write C with the structural benefits C++ classes provide, and there's nothing wrong with that. The oh-so-perfect STL and boost aren't available everywhere and don't necessarily suit every application. – James M Mar 09 '12 at 15:23
  • @JamesMcLaughlin: You're right. But "not everywhere" and "don't suit every application" requires a sense of perspective- that is, "not everywhere" meaning "Only not available on very minor embedded platforms" and "don't suit every application" meaning "Might not suit 0.00001% of applications"- i.e., whilst both are technically true, in reality, such questions are much too localized and it's perfectly reasonable to assume that they are available and do suit. – Puppy Mar 09 '12 at 15:26
  • @JamesMcLaughlin this type of code is utter crap and it is what tars the name of C++ as a horrible messy language. It also makes up half of the C++ question on stackoverflow (or at least bad style in general) that wouldn't have occurred otherwise. The reason C++ was created was to get away from that type of code with useful abstractions. – 111111 Mar 09 '12 at 15:28
  • @DeadMG I agree and I am sure if there was a special circumstance surrounding this code the OP would have mentioned it. – 111111 Mar 09 '12 at 15:33
  • actually, I still need char* and wchar_t* because im coding for win32 and unfortunately, the win32 API does not support std::string with most (if not all) calls :-( – Sebastian Mar 09 '12 at 16:31

1 Answers1

3

everthing about your code is bad in the eyes of C++, sorry. try this

#include <iostream>

class C {
    std::string s;
    C(const std::string& s_) 
    : s(s_){}
};

std::ostream& operator<<(std::ostream& os, const C& c){
    return os << c.s;
}

void func(C& c){
    // do what you need here
}

int main(){
    C c("hello");
    std::cout << c << '\n';
    func(c);
    std::cout << c << std::endl;
    return 0;
}

In this example you don't have to worry about memory allocation and destruction, printf format strings or strcpy. It is much more robust.

C with classes (which is what you are writing) is categorically wrong, and blindly ignores the features that were created to make the language safer and easier without overhead.

111111
  • 15,686
  • 6
  • 47
  • 62
  • i agree this is correct way, but I still wonder exactly why original code crashes. probably double free() – Nick Jul 08 '15 at 15:09
  • I know this is old... but thinking about the crash, it could be that the instance of the new "C" class that's created after the copy operation when 'func(o)' is called will call "free(..)" on 's', which has not been initialized. Automatic lifetime will call the destructor when 'func' exits, which calls free on an uninitialized 's'. Maybe. – Sean Aitken Nov 29 '15 at 01:31