1

I'm learning about pointers and structures and I ran into this hard to understand the problem for me. I have created this simple program for testing purpose:

#include <iostream>

struct testStructure
{
    int a = 0;
    int b = 0;
    int c = 400;
};

int main()
{
    struct testStructure* testStruct;
    testStruct = new testSctructure;

    std::cout << testStruct->c;

    delete testStruct;
    return 0;
}

the above program works just fine, it prints the value 400. But when i try to do it with malloc:

#include <iostream>

struct testStructure
{
    int a = 0;
    int b = 0;
    int c = 400;
};

int main()
{
    struct testStructure* testStruct;
    testStruct = (testStructure*)malloc(sizeof testStructure);

    std::cout << testStruct->c;

    free(testStruct);
    return 0;
}

it gives me this value: -842150451

Why? The above examples were written and build in Visual Studio 2019.

I know that in C++ you should almost always want to use new keyword but I wanted to experiment a bit.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
GreenVoice
  • 23
  • 3
  • 2
    In the second case, you have allocated memory, but it has not been initialized yet. Undefined behavior. – Eljay Aug 28 '20 at 18:14
  • `-842150451` is a magic debugging code. `0xcdcdcdcd` see here what that means: [https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations](https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations) – drescherjm Aug 28 '20 at 18:23

3 Answers3

3

new initializes the allocated memory with the class' constructor (which is implicit in this this case).

malloc performs no initialization, it just allocates a portion of memory. Reading uninitiazlied memory will have undefined behavior.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
2

Here's how your second example can be made to work. In general, this is not a recommended way of working with C++, but there are some valid use cases.

#include <cstdlib>
#include <iostream>

struct testStructure {
    int a = 0;
    int b = 0;
    int c = 400;
};

int main() {
    auto testStruct_memory = std::malloc(sizeof(testStructure));

    // In-place constructor.
    auto testStruct = new(testStruct_memory) testStructure();

    std::cout << testStruct->c << "\n";

    // In-place destructor.
    testStruct->~testStructure();

    std::free(testStruct_memory);
}
Eljay
  • 4,648
  • 3
  • 16
  • 27
2

In the case of malloc, you allocated a block of memory, but did not create an object. The testStructure constructor was not called.

You could call the constructor on the memory area with a placement new:

char* ptr = malloc(sizeof testStructure);
testStruct = new(ptr) testStructure;

but this is hard to read, confusing, hard to maintain, and fraught with risk. For example, you need

  • to free() not delete ptr
  • you need to similarly explicitly call the destructor.

So, not recommended.

Jeffrey
  • 11,063
  • 1
  • 21
  • 42