如何声明一个占用内存部分中所有可用空间的 C 数组?

发布于 2024-09-24 05:52:35 字数 650 浏览 13 评论 0原文

假设我有一个 128KB 的内存区域。在我的链接器指令中,我将此区域分为三个部分:

  • .section_text
  • .section_data
  • .section_bss

每个部分的大小在预编译时未知,但我已限制 .section_bss 使用 .section_text 和 .section_data 之后内存区域内的所有剩余空间被分配。

有什么方法可以声明一个用尽 .region_bss 中所有可用空间的 C 数组吗?假设它是唯一使用 .region_bss 的东西,这样它就可以安全地使用整个区域。出于示例目的,但显然是错误的:

char entire_bss[sizeof(.region_bss)];

以下是我对一些预期答复的预先答复。首先,我知道 sizeof() 不是这样工作的。我只是用它来传达一个想法。其次,假设这必须使用数组而不是指针来完成(使用指针求解是可能的并且相当简单)。第三,我知道我可以获得 .region_bss 的起始地址和结束地址,但我不知道有什么方法可以使用它们来调整数组的大小。至少没有任何方法可以在 C 中工作。

很可能没有办法做到这一点,但我希望那里的一些天才已经弄清楚了。如果您可以使其与 Green Hills 工具集一起使用,则额外加分。

Assume I have a 128KB memory region. In my linker directives I split this region into three sections:

  • .section_text
  • .section_data
  • .section_bss

The size of each section is unknown pre-compilation, but I have constrained .section_bss to use all remaining space within the memory region after .section_text and .section_data are allocated.

Is there any way I can declare a C array that uses up all available space in .region_bss? Assume it is the only thing using .region_bss so it can safely use the entire region. For example purposes but obviously wrong:

char entire_bss[sizeof(.region_bss)];

Here are my pre-answers to some anticipated responses. First, I know sizeof() doesn't work like this. I'm just using it to get an idea across. Second, assume this must be done with an array and not with pointers (solving with pointers is possible and fairly simple). Third, I'm aware I can get the start and end addresses of .region_bss, but I'm not aware of any way to use them to size my array. At least not any way that works in C.

There very well may be no way to do this, but I'm hoping some genius out there has figured it out. Extra credit if you can make it work with the Green Hills toolset.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

巾帼英雄 2024-10-01 05:52:35

有什么方法可以声明一个 C 数组,它会耗尽 .region_bss 中的所有可用空间?

简短的回答是“不”。

如果 GreenHills 使用 GNU 工具链和 binutils 并允许自定义 链接器脚本,然后您可以向应用程序命名空间添加一个变量 使用 PROVIDE 来标记128K 块的末尾。 (参见如何访问此类变量的示例 这里)。这样你就不会得到固定大小的 C 数组,但程序将能够找到数组的末尾,因此数组的大小通常足以满足 C 程序的需要。

如果您想使用纯 C99 来实现这一点,那么您可能会运气不好,因为它是 高度不可靠,因为它不在标准范围内。

Is there any way I can declare a C array that uses up all available space in .region_bss?

Short answer is "no."

If GreenHills is using GNU toolchain with binutils and allows customizing the linker script, then you can add into an application namespace a variable using PROVIDE to mark the end of the 128K block. (See an example how to access such variables here). You will not have a C array of fixed size that way, but program would be able to find the end of the array thus the size of the array what is generally sufficient for C programs.

If you want to accomplish that using pure C99, then you might be out of luck as it is highly unreliable as it is not covered by the standard.

向地狱狂奔 2024-10-01 05:52:35

通常,您执行此操作的方式如下:

extern char section_bss[];

添加一些额外的内容,以便编译器、汇编器和链接器知道 section_bss.section_bss 的别名(或类似的名称)。

要获得大小,您可能需要对 bss 末尾的符号执行相同的操作并找出差异。

Usually the way you do this is with something like:

extern char section_bss[];

With some extra stuff thrown in so that the compiler, assembler, and linker know that section_bss is an alias for .section_bss (or similar name).

To get the size you would probably be want to do the same thing for a symbol that is at the end of bss and find the difference.

顾忌 2024-10-01 05:52:35

不,你不能。原因也很容易理解。在编译阶段,没有 .bss 和 .data 的概念,这些是纯粹的链接器约定。编译器知道一些抽象概念(常量数据、静态数据、代码),但它们到链接器部分的映射只是一种约定,并且取决于链接器、操作系统和处理器甚至内存模型选项。例如,在构建位置无关代码时,通常将常量放入代码段中。在嵌入式平台上,有时您必须与这些事情作斗争,甚至因此必须调整您的编码风格(我们曾经有一个基于 80186 处理器的模型,该处理器是用 MS-C 5.1 编译器构建的,如果我们不能使用 < code>.data 部分(全局、初始化变量和静态),因为工具链将它们放入 ROM 中,

我们通过在整个构建过程结束时修补生成的二进制文件解决了您的类似问题。链接器生成的映射文件中不同部分的已用内存(这是一个选项,可以查找),并从给定模型的内存大小中减去它(我们有 256K、512K 和 896K 模型),然后设置其中之一因此,对这个大小的所有引用都必须通过这个全局变量来工作,这一点很重要,然后我们的 malloc/free 实现就会使用这个内存池。 。

No you can't. It's also easy to understand why. At the compilation phase there is no concept of .bss and .data these are pure linker conventions. The compiler knows some abstract concepts (const data, static data, code), but the mapping of them to the linker section is only a convention, and depending on linker, OS and processor or even memory model options. When building position independend code, often the constants are put in the code segment for example. On embedded platforms you sometime have to struggle with these things and even have to adapt your coding style because of that (we had once a model based in 80186 processors that were built with MS-C 5.1 compiler, were we couldn't use the .data section (global, initialized variables and statics) because the toolchain put them in the ROM.

We solved once a similar problem of yours by patching the generated binary at the end of the whole build process. We extracted the used memory of the different section from the map file generated by the linker (it's an option look it up), and subtracted it from the memory size of the given model (we had 256K, 512K and 896K models) and set one of the global constants with the right value. It was thus important that all references to this size work via this global variable. This memory pool was then used by our implementation of malloc/free.

撩发小公举 2024-10-01 05:52:35

您想要做的事情将非常依赖于平台。您最好的选择可能是将数组声明为 extern char the_array[],end_of_array[];在您的 C 文件中,然后可能在汇编语言源文件中,为 the_array 和 end_of_array 声明几个数据部分。然后安排链接器规范,以便 the_array 将位于自下而上分配的内容的末尾,而 end_of_array 将位于自上而下分配的内容的开头,并且它们之间不会有任何其他内容。这是可能的——我已经在某些平台上做到了——但仔细阅读链接器文档很重要,以确保链接器不会在您不期望的时候重新安排事情。

What you are seeking to do will be very platform dependent. Your best bet is probably to declare an array as extern char the_array[],end_of_array[]; within your C file, and then, perhaps in an assembly-language source file, declare a couple of data sections for the_array and end_of_array. Then arrange the linker spec so that the_array will be at the end of stuff that's allocated bottom-up, and end_of_array will be at the start of stuff that's allocated top-down, and nothing else will be between them. It's possible--I've done it on some platforms--but it's important to read the linker documentation carefully to ensure that the linker won't rearrange things when you don't expect it.

情话难免假 2024-10-01 05:52:35

有什么问题吗

extern char __ghsbegin_region_bss[];
extern char __ghssize_region_bss[];
#define entire_bss __ghsbegin_region_bss
#define sizeof_entire_bss ((size_t)__ghssize_region_bss)

?我可以想到至少一个你可能对这个答案不满意的原因,但它涉及 C++ 模板元编程魔法(即,entire_bss 的类型不会具有正确的大小,因此取决于其大小的模板会以不同的方式解析)。只要您不将数组的大小用于任何用途(在 C 中也是如此),这种方法应该没问题。

请注意,__ghssize_region_bss 不是编译时常量 - 它直到链接时才解析 - 因此 100% 无法将其放入 [...] 中编译时的数组类型。

请参阅 Green Hills 手册中有关“部分符号的开始、结束和大小”的章节。

What's wrong with

extern char __ghsbegin_region_bss[];
extern char __ghssize_region_bss[];
#define entire_bss __ghsbegin_region_bss
#define sizeof_entire_bss ((size_t)__ghssize_region_bss)

? I can think of at least one reason you might not be satisfied with this answer, but it involves C++ template metaprogramming magic (namely, the type of entire_bss wouldn't have the right size, so templates that depend on its size would resolve differently). As long as you don't use the size of the array for anything (and this is true, in C), this approach should be fine.

Note that __ghssize_region_bss is not a compile-time constant — it's not resolved until link-time — so there's 100% no way to get it inside the [...] of an array type at compile time.

See the chapter on "Beginning, End, and Size of Section Symbols" in the Green Hills manual.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文