【问题标题】:C++ Memory AllocatorC++ 内存分配器
【发布时间】:2020-05-12 13:12:51
【问题描述】:

我试图弄清楚如何创建一个链接到单字节数组的链表。所以我放入字节数组的每个元素都可以是 enqued() 和 dequeued()。但是,我需要弄清楚如何使用指针偏移和链表来做到这一点。

我的问题是: 如何从指针的开头获得设定量的偏移量?例如,假设我的列表的开头是一个指针。我将首先检查该空间是否为空,如果不是,则获取列表中的下一个值。如何从当前指针位置偏移并获得一个新的指针位置,该位置基本上只是另一个指针的偏移量,向前或向后,向上或向下,向左和向右,正负。

有人问了一个例子:

byte myData[1024];

我必须将我的所有数据存储到此。这是课堂作业。本质上,我必须使用这个数组来存储我的所有数据,并且基本上创建一个队列,就像标准的 c++ 队列一样。我必须创建 Enqueue() 和 Dequeue() 函数,然后为每个函数动态分配内存。我对自己在做什么有一个大致的了解。我一直试图弄清楚如何获取当前位置的指针,然后将其设置为新位置,然后将其作为列表中的“下一个”。

【问题讨论】:

  • 什么是单字节数组?你的意思是char singlebytearray[1];? 请在您的问题中提供一些minimal reproducible example,以便edit。 参考this C++ website 或n3337 C++ 标准。
  • 还要解释为什么你被禁止使用标准C++ containers,并解释你的目标架构是什么。假设的i286 或Arduino 与RISC-V(或IBM Z mainframze 完全不同,您可以找到两者的C++ 编译器(例如GCC...)
  • Basile,我添加了更多信息。我不知道这是否有帮助。
  • 您应该阅读诸如Introduction to algorithms 和一些C++ programming 之类的书。还要阅读一些textbook on operating systems,当然还要阅读n3337 C++ 标准。回答您的问题需要一本完整的书,我们没有时间专门为您写一本。
  • 链表还是数组表?你提到了两者,但它们是非常不同的东西。要回答您的评论,只需添加或减去指针。当指针存在时,应该已经涵盖了这一点。我认为问题在于,当您只需要指针运算时,您会抛出许多非常复杂的概念(分配器、内存偏移)。

标签: c++ memory memory-management


【解决方案1】:

听起来你真正想要的是指针运算。很简单。

std::int32_t foo[] = {42, 350};
std::int32_t* intPtr = &foo;  // We'll say foo is at address 0x005

++intPtr;  // Or intPtr += 1, either way the value of intPtr is now 0x009
           // *intPtr would now give you 350.
           // Your program knows the type being pointed to, and bumps up the address
           // accordingly. In this case a 4-byte integer

在 C 数组上进行指针运算时,重要的是要进行检查以防止您超出任一侧的范围。但是,我什至不认为指针算术是必要的。如果您要私下存储数组,只需使用索引访问并跟踪列表结束的索引会简单得多。您仍然需要进行检查,但它们的检查更容易。

您也说链表,但描述的是数组列表。它们是两种截然不同的数据结构。如果您编写一个单独的数组列表类,并在队列中存储一个数组列表对象或原始数组,您的队列将更容易编写。

【讨论】:

    【解决方案2】:

    如何从指针开始处获得设定量的偏移量?

    阅读 C++11 标准 n3337 了解 pointer 算法。注意 C++ 中的 existence of offsetof。

    如果您有两个包含有效地址的short*ptr1; 和short*ptr2; 指针,您可以编码ptr1 - ptr2 或ptr1 + 5 或ptr2 - 3(但禁止使用ptr1+ptr2)。 C++11 标准解释了何时有效(有时无效,例如当 ptr2 是 nullptr 时)。另请注意,通常&ptr1[3] 与ptr1+3 相同,而ptr2[-1] 恰好是*(ptr2-1)(在有意义的情况下)。

    当心你的代码中的undefined behavior,例如buffer overflows(如果你不小心进行指针运算,你就会有一个:当心segmentation faults)。

    address sanitizers、调试器(如GDB)、valgrind 等工具应该有助于理解代码的行为。

    不要忘记在 C++ 编译器中启用警告和调试信息。一旦您的 C++ 代码在没有警告的情况下编译,请阅读 how to debug small programs。使用GCC,编译使用g++ -Wall -Wextra -g。请注意,GCC 10 添加了一些static analysis abilities。您可以使用Clang static analyzer 或Frama-C(或开发自己的GCC plugin)。

    linked list wikipage 有一个不错的图。 tries 上的维基页面也可以为您提供帮助。

    我建议阅读一个好的C++ programming book,然后阅读一些introduction to algorithms。

    在 github 或其他地方,您可以找到大量与您的问题相关的 C++ 代码示例(其术语会让非英语母语人士感到困惑)。

    关于记忆形状分析的学术论文(例如this one 或that one)包含可以提高您的理解的图表。 Books 或 web resources about garbage collection 也是相关的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-24
      • 2015-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多