-3

I'm just decided to test malloc and new. Here is a code:

#include <iostream>
#include <string>

struct C
{
    int a = 7;
    std::string str = "super str";
};

int main()
{
    C* c = (C*)malloc(sizeof(C));
    std::cout << c->a << "\n";
    std::cout << c->str << "\n";
    free(c);
    std::cout << "\nNew:\n\n";
    c = new C();
    std::cout << c->a << "\n";
    std::cout << c->str << "\n";
}

Why an output of this program stops at std::cout << c->a << "\n";:

-842150451

C:\Code\Temp\ConsoleApplication12\x64\Debug\ConsoleApplication12.exe (process 22636) exited with code 0.

Why does compiler show no errors - I thought, std::string isn't initialized properly in case of malloc, so it should break something. If I comment out printing of the string, I'm getting a full output:

-842150451

New:

7
super str

C:\Code\Temp\ConsoleApplication12\x64\Debug\ConsoleApplication12.exe (process 21652) exited with code 0.

I use MSVS2022.

qloq
  • 689
  • 1
  • 5
  • 15
  • 3
    malloc should not be used in `c++`. It does not call the constructors. – drescherjm Jul 05 '22 at 19:13
  • `malloc` does not initialize your object. – Galik Jul 05 '22 at 19:13
  • 5
    [Undefined behavior](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) is what's going on. – Igor Tandetnik Jul 05 '22 at 19:14
  • `C* c = (C*)malloc(sizeof(C));` -- No `C` object was created. All malloc does is allocate a bunch of bytes. The compiler did exactly what you asked for -- `sizeof(C)` bytes, dumped in your lap. – PaulMcKenzie Jul 05 '22 at 19:14
  • 1
    The compiler could show the error, but you have suppresed it with the C type cast. – 273K Jul 05 '22 at 19:15
  • 3
    *I thought, std::string isn't initialized properly in case of malloc, so it should break something* -- C++ does not work this way. There is no guarantee that anything crazy you will do will crash a program. As you can see, the craziness of using `malloc` as if it created an object didn't crash your program. – PaulMcKenzie Jul 05 '22 at 19:18
  • C++ provides you enough rope to shoot yourself in the foot. The cast tells the compiler to "Shut up, I know what I'm doing." As it would turn out, the programmer would, in fact, not know what he was doing. – Eljay Jul 05 '22 at 20:08
  • Оh, minus-guys. The only thing I missed is undefined behavior - I was wrongly convinced that I SHOULD get a runtime error. Forgetting of `delete` is a simple and understandable consequence of using `new`. – qloq Jul 06 '22 at 12:17

2 Answers2

3

You've used malloc. One of the reasons to not do this is that it hasn't actually initialized your object. It's just allocated memory for it. As a result, when accessing member fields, you get undefined behavior.

You have also forgotten to delete the C object you created with new. But you may wish to use a std::unique_ptr in this scenario, to avoid having to explicitly delete the object at all. The smart pointer will automatically free the memory when it goes out of scope at the end of main.

auto c = std::make_unique<C>();

std::cout << c->a << std::endl;
std::cout << c->str << std::endl;
Chris
  • 26,361
  • 5
  • 21
  • 42
0

(C*) is an Explicit Conversion. It tells the compiler to shut up and do exactly what it was told to do, no matter how stupid that may be. You don't get an error message because the code explicitly told the compiler not to give you one.

To allow the programmer and compiler the maximum amount of leeway, C++ will not prevent you from doing some pretty insane things. It assumes you know what you are doing and are not trying to shoot yourself.

user4581301
  • 33,082
  • 7
  • 33
  • 54