0

As such:

class MyClass{
public:
    int *property;
    MyClass(){
        property = (int*)malloc(sizeof(int));
    }
    ~MyClass(){
        free(property);
    }
};

I understand that there are better ways to do this, but I don't think I understand why exactly this is incorrect.

arrowd
  • 33,231
  • 8
  • 79
  • 110
  • 6
    Tangent: This particular example is incorrect for reasons unrelated to `malloc` - it doesn't honour the [rule of three](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three/4172724). – Oliver Charlesworth Jan 30 '18 at 19:45
  • 2
    You allocated memory for an `int` but you don't construct it, so you can't use it. Also if you copy a `MyClass` you double `free`. Also you are re-inventing `std::unique_ptr`. – nwp Jan 30 '18 at 19:46
  • 2
    @nwp `int` is a [POD type](http://en.cppreference.com/w/cpp/concept/PODType). You can use an `int`that was allocated with `malloc`. – François Andrieux Jan 30 '18 at 19:47
  • 2
    Note that it would be UB to read or write `*property` without doing a placement-new on the storage obtained by `malloc` – M.M Jan 30 '18 at 19:49
  • 3
    @M.M That doesn't apply for [POD type](http://en.cppreference.com/w/cpp/concept/PODTypes). It's UB to read it, but only because it's unitialized. You can write to it without issue, and then read it without issue. – François Andrieux Jan 30 '18 at 19:49
  • There was a typo in the url of my last comment. It was meant to be http://en.cppreference.com/w/cpp/concept/PODType. – François Andrieux Jan 30 '18 at 19:57
  • @FrançoisAndrieux [see here for explanation](https://stackoverflow.com/a/40874245/1505939), there is no exception for PODs in intro.object/1. The cppreference text contradicts the standard – M.M Jan 30 '18 at 20:19
  • @M.M About about [basic.life/1] ([link](https://timsong-cpp.github.io/cppwp/basic.life))? Seems to me that since `int` is not a class type, (1.1) applies but (1.2) doesn't, which means it's lifetime begins immediately when appropriate storage is obtained. I guess the difference between object lifetime and object creation aren't as clear to me as I thought. – François Andrieux Jan 30 '18 at 20:42
  • @FrançoisAndrieux there is no object for which to have a lifetime begin . basic.life applies when we know there is an object being created (according to intro.object/1) and it specifies when that object's lifetime begins – M.M Jan 30 '18 at 20:47
  • @M.M Alright. I guess that implies all c code that uses dynamic allocation is not legal c++ code. – François Andrieux Jan 30 '18 at 20:51
  • @M.M I'm finally convinced - but I agree with Yakk in the comments of the linked questions: The standard should be fixed to allow this (in practise all implementations *do* allow it, because so much legacy code uses it). – Martin Bonner supports Monica Jan 30 '18 at 21:41
  • The discussion about lifetimes seem to ignore Rule 0 of C++: C code as it appears in K&R2 is also valid C++ code. Or the alternative wording "no gratuitous incompatibilities". Forcing a placement `new` in C++ is irreconcilable with C. – MSalters Jan 31 '18 at 12:17

3 Answers3

0

In general you should use new not malloc in c++ code. The only time not to do that is in extreme corner cases where you want to control exact location for some reason, building custom memory pools (and even then you should overload new so as not to call malloc directly in the class definition). In that case you use 'placement new'

The main reason to use new is that it will correctly construct the object that it just made. malloc will return garbage memory. Not relevant (maybe) for ints but certainly important for objects

amod
  • 4,190
  • 10
  • 49
  • 75
pm100
  • 48,078
  • 23
  • 82
  • 145
  • 1
    This is a good point, but doesn't answer the question. It would be best to express it as a comment. – François Andrieux Jan 30 '18 at 19:47
  • 1
    This is poorly phrased. "You should use `new` instead of `malloc`. Unless in some other case where you want placement `new`". Also I disagree that you should use `new` in C++. – nwp Jan 30 '18 at 19:50
0

Would there ever be a reason to initialize a pointer in a constructor with malloc?

At least couple of reasons comes to my mind:

  • you need to work with C code/library and pass pointer there that expected to be initialized by malloc()

  • You are limited with resources and want to be able to use realloc() with it

There could be more, but you need to be careful when working with raw pointers, either initialized by new or malloc(). For example your class violates rule of 3/5/0. Best way to handle that - use a smart pointer.

Also you need to remember that with malloc() you need to be sure that memory is properly initialized, it can be done with memset() or simple assignments with POD types or (and this is mandatory for non POD) through placement new. That usage is not trivial so you would want to deal with that when you really need it.

Slava
  • 43,454
  • 1
  • 47
  • 90
0

You have to make sure to disable copy constructor/assignment operator which are generated by default in c++. If you don't, you will have undefined behavior. E.g. Below code will destruct twice.

#include<cstdlib>

static int number_of_constructions = 0;
static int number_of_destructions = 0;

struct S {
    int * p;
    S() {
        p = (int*) malloc(sizeof(int));
        number_of_constructions++;
    }
    ~S() {
        free(p);
        number_of_destructions++;
    }
};

void foo() {
    S s;
    S s2 = s;    
}

Link: https://godbolt.org/g/imujg1

balki
  • 26,394
  • 30
  • 105
  • 151