【问题标题】:Initialized values of array of pointers in a struct结构中指针数组的初始化值
【发布时间】:2021-08-03 07:28:30
【问题描述】:

假设我定义了一个结构,其中包含指向对象的指针数组,如下所示:

struct node {
    node *arr[10];
};

然后,我在堆上初始化结构的一个实例并检查其指针数组的内容。

node *curr = new node;
for (int i = 0; i < 10; ++i) {
    if (curr->arr[i] == nullptr) std::cout << "null" << std::endl; 
} // this would print "null" 10 times in my tests in online IDEs and on QTCreator's C++ environment.

但是,为什么我看到数组的每个元素都是 nullptr?它不应该是一个垃圾值吗?这是所有带有指针数组的结构的默认行为吗?

我认为它们应该只是垃圾指针,而不是所有空指针。关于如何考虑初始化node 实例的任何提示都很棒!谢谢!

【问题讨论】:

  • “垃圾”的真正意思是“不确定的”——它们可能碰巧是空指针。 (确实,许多操作系统在首次将内存提供给进程时会将其归零,因此 如果 您从操作系统获取新内存,而不是从以前的 delete 重用内存,您将 更多可能会看到零。绝不保证!)
  • stackoverflow.com/questions/35666894/garbage-characters-in-c/… 解释的很好——对于字符,不是指针,但是原理是完全一样的。

标签: c++ pointers struct initialization


【解决方案1】:

这取决于内存分配器的状态,它是程序员的黑匣子。对于你的代码sn-p,我们可以查看对应的程序集:

f():                                  # @f()
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     edi, 80
        call    operator new(unsigned long)
        mov     qword ptr [rbp - 8], rax
        mov     dword ptr [rbp - 12], 0

只有操作符 new 被调用,因为结构是一个普通的旧数据类型,我们没有在这里调用一个重要的构造函数,我们分配的内存是不变的。

如果我们通过插入与您的结构完全相同大小的内存分配和释放来稍微更改代码:

#include <cstring>
#include <iostream>
#include <memory>
const size_t n = 10;
struct node {
  node *arr[n];
};

void f() {
  {
    std::unique_ptr<char[]> up(new char[sizeof(node)]);
    memset(up.get(), 0xff, sizeof(node));
  }

  node *curr = new node;
  for (int i = 0; i < n; ++i) {
    if (curr->arr[i] != nullptr) std::cout << "not null" << std::endl;
  }
}

int main(int argc, char *argv[]) {
  f();
  return 0;
}

我们现在得到垃圾值,这是因为我们分配了一个大小为sizeof(node)的内存块,并用值填充它然后立即释放它。

对于现代内存分配器,它们倾向于为不同大小范围保留一个内存池,以通过避免过于频繁的系统调用来提高性能(您可以参考jemalloc 的设计,libc 中的设计类似但更简单) .在我的代码中,我们分配了一个大小为sizeof(node) 的内存块并释放它,内存将由分配器持有。然后我们用node *curr = new node;分配一个节点,很可能我们会得到之前分配返回的相同地址。所以我们现在得到了expected垃圾值,对于多线程的复杂程序,情况就不同了,这里我们忽略复杂的场景。

在c++中初始化变量是一个好习惯,可以避免很多相关的bug,我建议总是这样做。

Online demo.

【讨论】:

    猜你喜欢
    • 2012-02-08
    • 2018-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    相关资源
    最近更新 更多