【问题标题】:Initializing a ref-to-ptr in a struct after malloc()在 malloc() 之后在结构中初始化 ref-to-ptr
【发布时间】:2015-01-01 00:56:16
【问题描述】:

我在使用 VC++ 和调试 CRT 和开发中的 DLL 时遇到问题。

我有一个这样的结构,包含一些引用。

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

现在它应该保存未初始化的 ref-to-ptrs,我想通过以下方式对其进行初始化:

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

它适用于一切,但 ref-to-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
};

然后使用placement new构造结构体:

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 = ...
    ...
}

释放整个事情需要通过调用 d'tor 和 free 来明确完成,因为我们使用 placement new

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

【问题讨论】:

  • 在 C 中,你没有参考;在 C++ 中,您不应该使用 malloc。选择您的语言。
  • 只是投反对票,为了什么?这是我面临的一个问题,有一段摘录可以了解它是如何工作的,我指出了一个解决方案......

标签: c++ c visual-studio-2012 struct msvcrt


【解决方案1】:

你不能在没有初始化的情况下声明引用。您的 struct 具有 no 默认构造函数,因为您明确声明了非默认构造函数。仅分配 malloc 不足以创建有效的 DATA 对象,因为它是 non-POD type

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

【讨论】:

    【解决方案2】:

    请注意,malloc() 返回未初始化的内存。需要构造 C++ 对象。将对象放入未初始化内存的方法是使用placement new(此代码还添加了清理):

    #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;
    

    【讨论】:

    • 只是好奇,你将如何释放那段内存(带有新位置的那个)?
    • 或根本没有分配:static DATA data(..); static DATA* dataptr = &amp;data;.
    • @Jarod42:是的,有很多方法。不过,如果需要使用malloc(),清理起来也很有趣……
    • 这在使用placement new 时可能对清理有用:stackoverflow.com/questions/8918791/…
    • @DominikP:我更喜欢使用std::unique_ptr&lt;...&gt;(),但是,是的,摆脱这些家伙并不是完全直截了当的。
    猜你喜欢
    • 2019-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-17
    • 1970-01-01
    • 1970-01-01
    • 2021-06-18
    • 2016-03-20
    相关资源
    最近更新 更多