Initializing a class using malloc

匆匆过客 提交于 2020-01-15 05:57:45

问题


I am working on a toy language for avr using C++ as the intermediate language, Problem is avr-gcc does not have new implemented. All my object derive from the class Object which has virtual methods when I create say a float object with malloc using instructions from,

Can I implement the Factory Method pattern in C++ without using new?

as soon as I cast it to an Object to pass around and back to a Float my program crashes, comments in the answer says that this is due to vtable not initializing properly, so how can i create a c++ object without using new and have the vtable setup properly?


回答1:


It appears that new as a language construct is supported, but the operator new code that underlies it and does the actual allocation isn't implemented.

It should be pretty easy to fix that by providing your own implementation for operator new in your source code:

In some header file that's included in any file needing new

#include <stdlib.h> 

void * operator new(size_t size); 
void operator delete(void * ptr);

In a single cpp file.

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

void operator delete(void * ptr) 
{ 
  free(ptr); 
} 

Source: this post on avrfreaks.net, which also contains information about some other stuff you may want/need to implement on your own.




回答2:


It depends on the hardware platform you are compiling to, but the layout is usually pretty similar across implementations. After all, the first C++ was CFRONT, which compiled C++ to C...

The platform-dependent issues and the memory layouts will be described in a "platform C++ ABI" where ABI stands for "Application Binary Interface."

struct Cxx_ABI_Header
{
    unsigned inheritance_backward_offset;  /* Must be Zero for base object */
    unsigned rtti; /* Each class has its own signature. */
    void * vtable; /* Pointer to array of virtual function pointers. */
}

struct object_one
{
     char * file_name;
     int file_descriptor;
}

int object_one_create_file(struct object_one *);
int object_one_delete_file(struct object_one *);
int object_one_update_file(struct object_one *, off_t offset, 
                           size_t nbytes_replace, size_t nbytes_supplied,
                           char * buf);
int object_one_read_file(struct object_one *, off_t offset, 
                         size_t nbytes_read, char * buf);
int object_one_op_noauthz(struct object_one *)
{
    return ENOACCESS;
}

void * CRUD_vtable_authenticated_user = {
    { object_one_create_file, object_one_read_file,
      object_one_update_file, object_one_delete_file }};

void * CRUD_vtable_guest = {
    { object_one_op_noauthz, object_one_read_file,
      object_one_op_noauthz, object_one_op_noauthz }};

Here is a possible constructor, which actually makes two different kinds of "object_one".

struct object_one * new_object_one(char * filespec, int user_id)
{
    size_t n_bytes = sizeof(struct Cxx_ABI_Header) + sizeof(struct object_one);
    void * pheap = malloc(n_bytes);
    struct * pCxx_ABI_Header pcxx = pheap;
    struct * pObject  pobj = (void *)((char *)pheap 
                                               + sizeof(struct Cxx_ABI_Header));

    if (!pheap) ...

    pcxx->inheritance_backward_offset = 0;
    pcxx->rtti = /* You tell me? */
    pcxx->vtable = (userid < 0 ) ? CRUD_vtable_guest 
                                 : CRUD_vtable_authenticated_user;

    pobj->file_name = strdup(filespec);
    pobj->file_descriptor = 0;

    return pobj;
}

Voila - polymorphism via ?:

Anyway, enjoy the language experimentation and good luck improving on C++. By basing your efforts on C, you would be off to a solid start. ;)




回答3:


You can use malloc followed by placement-new which will create the object properly, constructing it at the location you specify.

Of course that still means using the keyword "new" but if what you really want to do is handle the memory / heap management and not put a total ban on that keyword then it might achieve what you are trying.




回答4:


If you want to tailor the implementation to one specific version of a specific compiler, then yes, for GCC simply look into the implementation of new in the GCC code.

Otherwise no. What you can do is two-factor initialization. First allocate the memory (malloc() or operator new()) and then initialize using placement new.



来源:https://stackoverflow.com/questions/5613982/initializing-a-class-using-malloc

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!