C++ why does new keyword works and malloc does not? - c++

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.

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.

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);
}

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.

Related

C++ moving a unique_ptr to a struct member

I have the following program -
#include <iostream>
#include <memory>
class Person
{
public:
Person(const std::string& name):
name(name) { }
~Person() { std::cout << "Destroyed" << std::endl; }
std::string name;
};
typedef struct _container
{
std::unique_ptr<Person> ptr;
}CONTAINER;
void func()
{
CONTAINER* c = static_cast<CONTAINER*>(malloc(sizeof(CONTAINER)));
std::unique_ptr<Person> p(new Person("FooBar"));
c->ptr = std::move(p);
std::cout << c->ptr->name << std::endl;
}
int main()
{
func();
getchar();
return 0;
}
The program prints "FooBar". I expect the program to print "Destroyed" when func() return but it does not. Can someone help me with why that would not be happening in this case?
You've actually got undefined behaviour here.
You cant just cast a malloc'd buffer to an object type. The constructors are never called and your member variables are in an invalid state.
You need to do either:
void func()
{
CONTAINER c;
std::unique_ptr<Person> p(new Person("FooBar"));
c.ptr = std::move(p);
std::cout << c.ptr->name << std::endl;
}
Or
void func()
{
CONTAINER * c = new CONTAINER();
std::unique_ptr<Person> p(new Person("FooBar"));
c->ptr = std::move(p);
std::cout << c->ptr->name << std::endl;
delete c;
}
or if you really want to use malloc - you'll need to use placement new to get the right behaviour - but usually you dont want that, so I wont elaborate for now...
You forget to add this line at the end of func().
delete c;
Here is the test (ideone).
c is a raw pointer. It is not a smart pointer.
Thus, you have to delete it manually.
Deleting c will automatically delete CONTAINER::ptr because CONTAINER::ptr is a unique pointer.
However, you have malloc yourself, the more proper code might be :-
c->~_container();
Then free(), but I don't think it is needed in this case, because CONTAINER is not on a heap.
( I have never used malloc, so I am not sure about this part. )
Edit:
My solution is a quick patch to solve a single problem. (not print "Destroyed")
Please also read Michael Anderson's solution.
It addresses another underlying issue of the OP's code. (malloc)
Edit2:
Here is a good link about placement new that Michael Anderson mentioned.
The code below is copied from the link (with little modification):-
int main(int argc, char* argv[]){
const int NUMELEMENTS=20;
char *pBuffer = new char[NUMELEMENTS*sizeof(A)];
//^^^ difference : your "CONTAINER" could be char[xxxx] (without new)
A *pA = (A*)pBuffer;
for(int i = 0; i < NUMELEMENTS; ++i) {
pA[i] = new (pA + i) A();
}
printf("Buffer address: %x, Array address: %x\n", pBuffer, pA);
// dont forget to destroy!
for(int i = 0; i < NUMELEMENTS; ++i){
pA[i].~A();
}
delete[] pBuffer;//<--- no need to delete char[] if it is a stack variable
return 0;
}
For further detail, please see that above link (because I don't want to copy more of it to here).
Here is another useful link : Using malloc in C++ is generally not recommended.

Issue with struct constructor causing stack overflow

Both sections of code below are drastically simplified, isolated versions of my actual code. The examples are just big enough to reproduce the problem. The first section of code below works fine. The section section is an attempt to begin to make it part of a class. I'm trying to take tiny steps since small modifications to something like the struct shown below require lots of changes throughout the code which is full of pointers, pointer to pointers and references which all involve this struct. Can you tell me why the second section of code throws a stack overflow within it's constructor and what small changes can be made to fix it?
Working code:
#include <cstdio>
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
const int maxSize = 3;
struct Item{
int count;
Item *items[maxSize + 1];
};
void foo()
{
Item *p;
p = new Item();
p->count = 2;
cout << p->count << endl;
}
int main(int argc, char *argv[])
{
foo();
return 0;
}
Attempt to very gradually modify the code as a whole toward becoming a class:
#include <cstdio>
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
int maxSize = 3;
struct Item{
int count;
Item *items;
Item()
{
items = new Item[maxSize + 1]; // stack overflow
}
};
void Initialize(int size)
{
maxSize = size;
}
void foo()
{
Item *p;
p = new Item();
p->count = 2;
cout << p->count << endl;
}
int main(int argc, char *argv[])
{
Initialize(5);
foo();
return 0;
}
The first call to construct a Item calls new Item[maxSize+1], which calls the default constructor, which calls new Item[maxSize+1], which calls the default construct, and so on until you reach stack overflow.
All the answers are right. I want to suggest a solution for you:
Instead of initializing the array within the ctor, you could implement an initialization method like
init(int maxSize) {
items = new Item[maxSize + 1];
}
that you can call after having constructed the object. This should avoid the stack overflow. In general, you should avoid to place instances of an object inside the object itself. Its better to use Collections of the Item
List<Item>, std::vector<Item>, ...
It is because in working version you have reference to an array of object, but not actual object of Items. In second version, you are creating objects by using keyword new. So, in second version in constructor it will call itself! It will call it's own constructor infinite times. Hence, you see runtime exception stackoverflow :)
Above posters are right. Within the constructor of Item you create items (by creating an array). So the ctor is again called, which creates more items, which .... This is more or less an infinite loop which eats up your stack.
Either stick with the references or use a collection like List - so you can add the items later on dynamically.

Using static object in overloaded global new operator cause core dumped run time error

In this code I tired to simply know which object I forget to delete so I made a singleton with one static object to count the new allocated objects, but using this object inside global new function causes error, the same error occurs if I want to use standard objects like cout. What could be the cause of that error and what is the proper way to get the same effect?
#include <vector>
#include <cstdlib>
#include <new>
#include <iostream>
class Count_new { //singleton
std::vector<void*>count_v ; // to get "new" pointers
Count_new(){}
Count_new(const Count_new&);
public:
void count(void * m) {
count_v.push_back(m);
}
static Count_new * instance(){
static Count_new c ;
return &c;
}
~Count_new()
{
unsigned int index = 0 ;
while (index < count_v.size()) {
if(count_v.at(index) != NULL)
std::cout << count_v.at(index) << " not deleted\n" ;
}
}
};
Count_new &c = *Count_new::instance();
void * operator new (size_t sz) throw (std::bad_alloc){
void *m = malloc(sz);
c.count(m); //produce Error core dumped
return m;
}
class Obj{};
int main() {
try {
Obj *p1 = new Obj ;
Obj *p2 = new Obj ;
}catch(std::bad_alloc&b){
std::cout << "Error in memory allocation:" << b.what()<< "\n";
}
}
The problem is you're hitting endless recursion. You've replaced the global ::operator new which is used by everything by default. This includes the allocation performed by the default allocators, such as the one std::vector<T> uses. So your call to count calls push_back, which needs to reallocate, which eventually calls ::operator new, which calls count, which ...
If you want to keep this scheme, you'll have to write allocator which doesn't use ::operator new, and then modify the type of count_v to use that allocator.
Oh and I'd drop the dynamic exception specification, they're deprecated since C++11.

C++ Vectors and struct pointers

My struct has a vector of integers. However, when dynamically creating an instance of the struct, I can't seem to access the vector.
#include <stdlib.h>
#include <iostream>
#include <vector>
using namespace std;
typedef struct {
vector<int> intList;
} astruct;
int main()
{
astruct* myStruct = (astruct*) malloc(sizeof(astruct));
myStruct->intList.push_back(100);
cout << "Hello world!" << endl;
free(myStruct);
return 0;
}
Attempting to add 100 to the struct's vector crashes the program. Hello world! is never shown. What's going on?
Your vector is never initialized as you simply cast an allocated memory region to a astruct*, therefor the constructor of your struct and as consequence the constructor of std::vecotr is never called. Use the new operator instead.
astruct* myStruct = new astruct();
myStruct->intList.push_back(100);
delete myStruct;
You should not use malloc()/free() in C++ program, especially for creating C++ object, unless you know what you are doing. So use new/delete instead:
int main()
{
astruct* myStruct = new astruct;
myStruct->intList.push_back(100);
cout << "Hello world!" << endl;
delete(myStruct);
return 0;
}

deallocating gsl vectors in structs

Can you explain what's going on with my code here? I'm not sure if I'm using the destructor correctly or not in the struct.
With the destructor in there I get:
function1: 23
function2: 8.86183e-317
* glibc detected ./a: double free or corruption (fasttop): 0x000000000111b010 **
If I just comment out the destructor I get:
function1: 23
function2: 24
which is what I want. But don't I need the destructor to avoid a memory leak for a more complicated program?
(As you can see I may be a bit confused on pointers/allocation in general)
Thanks!
Edit: oh yeah, and why does the extra allocation step in function1 make a difference?
Edit2: Should I be initializing x = 0 in the constructor? I thought that was proper...should I be allocating it on initialization when I do this? So instead: x = gsl_vector_alloc(1).
#include <iostream>
using namespace std;
#include <cassert>
#include <cmath>
#include <gsl/gsl_vector.h>
struct struct1{
gsl_vector * x;
struct1() {
x = 0;
}
~struct1() {
if (x) gsl_vector_free(x);
}
};
void function1(void *p) {
struct1 s = *(struct1 *) p;
s.x = gsl_vector_alloc(1);
gsl_vector_set(s.x, 0, 24);
}
void function2(void *p) {
struct1 s = *(struct1 *) p;
gsl_vector_set(s.x, 0, 24);
}
int main() {
struct1 s;
s.x = gsl_vector_alloc(1);
gsl_vector_set(s.x, 0, 23);
function1(&s);
cout << "function1: " << gsl_vector_get(s.x, 0) << endl;
function2(&s);
cout << "function2: " << gsl_vector_get(s.x, 0) << endl;
return 0;
}
Inside of function1 and function2 you make a copy of the struct1 object that you create in the main() function. These copies have the same pointer x. When the destructor for each of these copies is called, gsl_vector_free is called, so you try to call it three times on the same pointer:
once in function1 when s is destroyed
once in function2 when s is destroyed
once in main when s is destroyed
You need to implement a copy constructor and copy assignment operator for this class. Any time you have a class that owns a resource, you need to implement these two functions and a destructor. A resource is anything that needs to be cleaned up when you are done using it.
In your sample code, it would be far better to encapsulate all of the allocation and deallocation inside of the class so that you can use the class without worrying about it. Make the class actually manage its resource.