0

I'm trying to replace operator new and delete with malloc and free (I got reasons for that). The problem is shown in code below:

std::string *temp = (std::string *)malloc(sizeof(std::string) * 2); // allocate space for two string objects.
temp[0] = "hello!";
temp[1] = "world!";
for(int i = 0; i < 2; i++)
{
    printf("%s\n", temp[i].c_str());
}
free(temp);
return 0; // causes SIGSEGV.

however..

std::string *temp = new std::string[2];
temp[0] = "hello!";
temp[1] = "world!";
for(int i = 0; i < 2; i++)
{
    printf("%s\n", temp[i].c_str());
}
delete [] temp;
return 0; // works fine

Why? and could anyone suggest me what is a right way to replace these operators with malloc and free?

Regards.

EDIT: this is just example, I'm not using standard C++ library.

EDIT: what about something like this?

class myclass
{
    public:
        myclass()
        {
            this->number = 0;
        }
        myclass(const myclass &other)
        {
            this->number = other.get_number();
        }
        ~myclass()
        {
            this->number = 0;
        }
        int get_number() const
        {
            return this->number;
        }
        void set_number(int num)
        {
            this->number = num;
        }
    private:
        int number;
};

int main(int argc, char *argv[])
{
    myclass m1, m2;
    m1.set_number(5);
    m2.set_number(3);

    myclass *pmyclass = (myclass *)malloc(sizeof(myclass) * 2);

    pmyclass[0] = myclass(m1);
    pmyclass[1] = myclass(m2);

    for(int i = 0; i < 2; i++)
    {
        printf("%d\n", pmyclass[i].get_number());
        pmyclass[i].myclass::~myclass();
    }

    free(pmyclass);

    return 0;
}
Nika
  • 1,864
  • 3
  • 23
  • 44
  • 7
    malloc and free don't call the constructor or destructor – Adam Oct 12 '13 at 23:00
  • If you really need to use `malloc`, why don't you write your own allocation function to replace the default one? And if you can't do that, you'll have to use placement-new (and explicitly call the dtor). – dyp Oct 12 '13 at 23:02
  • 11
    Whatever your reasons are, they're erroneous. – Jonathan Potter Oct 12 '13 at 23:02
  • 2
    `malloc` allocates memory. `new` constructs objects. Those are different things. – Kerrek SB Oct 12 '13 at 23:13
  • 2
    And, most importantly, C and C++ are different languages. Don't write C code if you claim to be writing C++ code. Or don't claim writing C++ if you really write C. –  Oct 12 '13 at 23:18
  • possible duplicate of [Segmentation fault](http://stackoverflow.com/questions/15296376/segmentation-fault) –  Oct 12 '13 at 23:20
  • 1
    "*I got reasons for that*" -- It would really help to know what those reasons are. – Keith Thompson Oct 12 '13 at 23:49
  • The system where I'm working doesn't exist c++ standard library, I'm using only classes from C++, other stuff is written only in plain C. – Nika Oct 13 '13 at 13:25
  • using g++ and command line options are: -nostdlib -nostartfiles -fno-exceptions – Nika Oct 13 '13 at 13:26

3 Answers3

7

malloc and free do not call the constructor and destructor of C++ classes. It also does not store information about the number of elements allocated in the array (like you are doing). This means the memory is simply allocated but never initialized. You can still manually construct and destroy the object however.

You should start by constructing the object by using placement-new. This requires you to pass the a pointer to the location where the object is to be created and to specify the type of object that needs to be instantiated. For example the first line where you assign a string literal to the allocated (but uninitialized) string object would look like the following:

new(&temp[0]) std::string("hello!");

Once you are done with the strings you need to destroy them by calling their destructor directly.

temp[0].std::string::~string();

The code you posed would look something like this:

// allocate space for two string objects.
std::string *temp = (std::string *)malloc(sizeof(std::string) * 2); 

// Using placement-new to constructo the strings
new(&temp[0]) std::string("hello!");
new(&temp[1]) std::string("world!");

for (int i = 0; i < 2; i++)
{
    printf("%s\n", temp[i].c_str());
}

//  Destroy the strings by directly calling the destructor
temp[0].std::string::~string();
temp[1].std::string::~string();
free(temp);
Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
  • operator new is in standard C++ library, as I said, I'm not using it, +1 for mentioning manual destruction. – Nika Oct 13 '13 at 10:55
  • I'm just trying to find a way, which will implement operator new and delete, without using standard C++ library but only standard C library. any suggestions? – Nika Oct 13 '13 at 11:01
4

If you really want to go down this rabbit hole... well, you need placement new and you need to call destructors manually. Here's how that looks:

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

int main()
{
    std::string *temp = (std::string *)malloc(sizeof(std::string) * 2); // allocate space for two string objects.
    new (&temp[0]) std::string("hello!");
    new (&temp[1]) std::string("world!");
    for(int i = 0; i < 2; i++)
    {
        printf("%s\n", temp[i].c_str());
    }
    temp[1].std::string::~string();
    temp[0].std::string::~string();
    free(temp);
    return 0;
}

Since malloc gives you an uninitialized memory block, you need to construct the objects in the appropriate memory slots and, before freeing the memory, you have to manually destruct them.

Community
  • 1
  • 1
Daniel Frey
  • 55,810
  • 13
  • 122
  • 180
2

You want to implement your own operator new() with malloc, not to replace operator new with malloc.

To implement operator new(), just write it like you would do with any other function.

void* operator new() (size_t sz) { return malloc(sz); }

If you want a standard-compliant version that throws std::bad_alloc on failure, just insert your code for that.

operator delete is left as an exercise for the reader, and so are operator new[]() and operator delete[]().

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • That's what I'm trying, but the function you provided, doesn't call constructor of object. – Nika Oct 13 '13 at 13:58
  • @OvérFlôwz: it does not and should not deal with objects and their constructors. Its task is to allocate memory. Constructors are called when you use [the new operator, which is different from operator new()](http://stackoverflow.com/questions/8962467/why-is-the-new-operator-allowed-to-return-void-to-every-pointer-type/8962536#8962536). – n. m. could be an AI Oct 13 '13 at 14:41
  • I still don't get it. Is not there ANY way to do it without new and delete? – Nika Oct 13 '13 at 15:30
  • I don't understand your problem. Could you be more specific? If you hsve tried the method I have described, and it doesn't work for you, please explain what doesn't work. If you don't understand why it should work, read a linked answer, do a google search, ask a question here. If you want to avoid the new and delete keywords/functions, *just because*, I can't help you. – n. m. could be an AI Oct 13 '13 at 16:05
  • do you mean, if I just implement operator new and return allocated memory with malloc, it will call constructor too? – Nika Oct 13 '13 at 16:26
  • Yes I pretty much do mean exactly that. – n. m. could be an AI Oct 13 '13 at 16:31
  • Wow, now I guess it is linker job, (my English skills are not so good, thats why I don't understood that. Thank you very much!) – Nika Oct 13 '13 at 16:44