在malloc()之后初始化结构中对ptr的引用

Initializing a ref-to-ptr in a struct after malloc()

本文关键字:ptr 引用 结构 初始化 malloc 之后      更新时间:2023-10-16

我在开发过程中遇到了使用VC++和带有DLL的调试CRT的问题。

我有一个类似的结构,包含一些引用。

struct DATA
{
    TA*& a;
    TB*& b;
    TC*& c;
    TD*& d;
    char** chars;
    int num_chars;
private:
    // because:
    // DATA a;
    // DATA b;
    // a = b; // is impossible
    DATA& operator=(const DATA&); // append " = delete;" for C++11
    // Default ctor (private because struct should be manually constructed using malloc)
    DATA(TA*& a, TB*& b, TC*& c, TD*& d)
        : a(a),
          b(b),
          c(c),
          d(d),
          chars(NULL),
          num_chars(0)
    {}
};

并像这样构建:

DATA*& Get()
{
    static struct DATA *data = (struct DATA*)malloc(sizeof(struct DATA));
    return data;
}

现在它应该保存未初始化的对ptrs的引用,我想通过初始化它

void func(TA* a, TB* b, TC* c, TD* d)
{
    Get()->a = a;
    Get()->b = b;
    Get()->c = c;
    Get()->d = d;
    ...
}

它适用于所有事情,但引用ptrs。。

当我使用WinDbg(在远程内核调试"kd"实例中)执行!analyze -v -f时,我在第一个Get()->a = a;上得到了一个INVALID_POINTER_WRITE_FILL_PATTERN_cdcdcdcd

谢谢你的帮助!:)

编辑:解决方案

解决方案是使用正确答案中的要点。

公开c'tor是必要的:

struct DATA
{
    TA*& a;
    TB*& b;
    TC*& c;
    TD*& d;
    char** chars;
    int num_chars;
    // Default ctor
    DATA(TA*& a, TB*& b, TC*& c, TD*& d)
        : a(a),
          b(b),
          c(c),
          d(d),
          chars(NULL),
          num_chars(0)
    {}
private:
    // because:
    // DATA a;
    // DATA b;
    // a = b; // is impossible
    DATA& operator=(const DATA&); // append " = delete;" for C++11
};

然后用CCD_ 4构造结构体:

DATA*& Get(...)
{
    // ... some stuff, overloading, other init-method etc. to init and construct like:
    static struct DATA *data = 
        new(malloc(sizeof(struct DATA))) DATA(...); // At least assign ALL references in the c'tor
    return data;
}

然后使用它,也许可以分配所有没有参考的东西:

void func(TA* a, TB* b, TC* c, TD* d)
{
    Get(a, b, c, d);
    Get()->chars = ...
    ...
}

释放整个过程需要通过调用'tor和free来显式完成,因为我们使用placement new:

data->~DATA();
free(data);

您不能在不初始化引用的情况下声明引用。您的struct没有默认构造函数,因为您显式声明了一个非默认构造函数。仅仅分配malloc不足以创建有效的DATA对象,因为它是非POD类型。

只需继续尝试声明一个真正的默认构造函数(即DATA() {}),您就会发现由于引用成员的原因,这将不起作用。如果要使用malloc来分配非POD对象,则必须使用放置new

请注意,malloc()返回未初始化的内存。需要构造C++对象。将对象放入未初始化内存的方法是使用placementnew(此代码还添加了清理):
#include <new>
DATA*& Get()
{
    static DATA *data = new(malloc(sizeof(struct DATA))) DATA(...);
    static std::unique_ptr<DATA, void(*)(DATA*)> clean(data,
                                                [](DATA* d){
                                                    d->~DATA();
                                                    free(data);
                                                });
    return data;
}

C++中没有重新设置引用的方法,也就是说,它们需要在构造过程中设置。就我个人而言,我不会使用malloc(),而是一个合适的分配:

    static DATA* data(new DATA(...));

或者,正如Jarod42所指出的,实际上是

    static DATA data(...);
    return &data;