简体   繁体   English

C语言中任意内存的类型

[英]A type for arbitrary memory in C

This is in reference to this question 这是参考这个问题

How to implement the c malloc/realloc functions properly? 如何正确实现c malloc / realloc函数?

where the accepted answer mentions that a char array can be used to model a pool of arbitrary memory. 接受的答案提到可以使用char数组对任意内存池进行建模。

However one of the comments to that accepted answer states 但是,对该已接受答案的评论之一指出

A char array that doesn't have allocated storage duration can only be aliased by a character type. 没有分配存储时间的char数组只能以字符类型作为别名。 In other words it cannot and it should not be used as arbitrary memory 换句话说,它不能也不应用作任意内存

Is this correct? 这个对吗? If so, then what could be used? 如果是这样,那么可以使用什么呢? I'd like to avoid using alloc or any specific OS calls - so I'm symmetrical with that question. 我想避免使用alloc或任何特定的OS调用-所以我对这个问题持对称态度。

There are different problems around. 周围有不同的问题。 First as shown by @Magisch's answer the related question was returning a dangling pointer causing Undefined Behaviour and generally execution errors. 首先,如@Magisch的答案所示,相关问题是返回一个悬空指针,导致未定义行为和一般执行错误。

The second one is related to the @^*# (censorship here) strict aliasing rule. 第二个与@ ^ *#(此处为检查)严格的别名规则相关。 Common compilers produce correct code when you use a character array as a large buffer to allocate any type from it, provided you ensure correct alignment. 当您将字符数组用作大缓冲区以从中分配任何类型时,如果您确保正确对齐,则普通编译器会生成正确的代码。 After all, this is the way they have to implement the malloc , realloc , and free routines. 毕竟,这是他们必须实现mallocreallocfree例程的方式。 And as they are part of the hosted environment (C standard library), the compiler developpers are not masochist enough to fordib that usage. 而且,由于它们是托管环境 (C标准库)的一部分,因此编译器开发人员还不足以禁止其使用。

But the C standard is a bit more strict here. 但是C标准在这里更加严格。 You should read my own answer here to a similar question and particularly @EOF's comment to it: 您应该在此处阅读我对类似问题的答案,尤其是@EOF对它的评论:

You cannot parcel of parts of an object declared as char [] into objects of other types (except character types), because they do have a declared type... which means technically you can't implement malloc() in pure C 您不能将声明为char []的对象的一部分打包为其他类型(字符类型除外)的对象,因为它们确实具有声明的类型...这意味着从技术上讲,您不能在纯C语言中实现malloc()

Aliasing refers to the strict aliasing rule that governs how the compiler is allowed to use registers. 别名是指严格的别名规则该规则控制如何允许编译器使用寄存器。 If you have pointers of different type referring to the same memory location, then writing done through one pointer type may not be noticed when reading through the other pointer type because the compiler is allowed to cache the data in registers. 如果您具有指向同一存储器位置的不同类型的指针,则在通过另一种指针类型进行读取时可能不会注意到通过一种指针类型完成的写入,因为允许编译器将数据缓存在寄存器中。

When you implement a memory pool, this problem is usually moot, because the pool implementation doesn't read/write to the memory. 当您实现一个内存池时,这个问题通常是没有解决的,因为该池实现不会对内存进行读/写操作。

If you want arbitrary types, then the safest bet is a union. 如果要使用任意类型,那么最安全的选择是联合。 Not only will it "beat" the strict aliasing rule, it will also ensure correct alignment. 它不仅会“击败”严格的别名规则,还将确保正确的对齐方式。 Remember that malloc and friends ensure alignment suitable for any type while auto doesn't. 请记住, malloc和Friends确保适合任何类型的对齐方式,而auto不适合。

The issue is alignment. 问题是对齐。 On processors that have alignment restrictions, a char array may not start at an address suitable for storing larger objects, like int or double . 在具有对齐限制的处理器上, char数组可能不会从适合于存储较大对象(例如intdouble的地址开始。

So to be safe, you need to make sure the char array is aligned properly for any type. 为了安全起见,您需要确保char数组对于任何类型都正确对齐。 If you're using a C11 compiler, then you can force alignment like this 如果您使用的是C11编译器,则可以像这样强制对齐

#include <stddef.h>
#include <stdalign.h>

_Alignas(max_align_t) char buffer[SIZE];

For older compilers, __attribute__((aligned(SIZE))) may be a solution. 对于较旧的编译器, __attribute__((aligned(SIZE)))可能是一个解决方案。 Otherwise, you need to look for a #pragma that forces alignment. 否则,您需要查找强制对齐的#pragma

And as discussed in various comments/answers, you should definitely disable the strict aliasing optimization with the -fno-strict-aliasing option. 而且,正如在各种注释/答案中所讨论的,您绝对应该使用-fno-strict-aliasing选项禁用严格的别名优化。 If that option (or the equivalent) doesn't exist, then you need to determine the optimization level that relies on the strict aliasing rule, and only use a lower optimization level. 如果该选项(或等效选项)不存在,则需要确定依赖于严格别名规则的优化级别,并且仅使用较低的优化级别。

I believe the issue he pointed out was that if you allocate a char type array statically and then compile your library with a modern, desktop-like C compiler like gcc, you cannot easily convert the contents of that area to another type. 我认为他指出的问题是,如果您静态分配一个char类型的数组,然后使用像gcc这样的现代,类似于桌面的C编译器来编译您的库,则无法轻松地将该区域的内容转换为另一种类型。 Because then the compiler would perform optimizations based on pointer aliasing and screw everything up, see "the strict aliasing rule" . 因为这样编译器将基于指针别名执行优化并将所有事情搞砸,因此请参阅“严格的别名规则”

Simply assure that your compiler does not use strict aliasing and you'll be fine. 只需确保您的编译器不使用严格的别名就可以了。 For example, none of the common embedded systems compilers on the market does this. 例如,市场上没有一个普通的嵌入式系统编译器可以做到这一点。

With gcc you'd compile as -fno-strict-aliasing . 使用gcc时,您将编译为-fno-strict-aliasing Might be good to always enable warnings for code that would cause such problems -Wstrict-aliasing . 始终为可能导致此类问题的代码启用警告可能会很有用-Wstrict-aliasing

As a side note, uint8_t makes far more sense to use as generic type, because unlike char , it is completely unambiguous: it has no signedness and the size is well-known. 附带说明一下,将uint8_t用作泛型类型更有意义,因为与char不同,它是完全明确的:它没有签名,并且大小是众所周知的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在没有动态内存分配的情况下复制C中的任意类型 - Copy Arbitrary Type in C Without Dynamic Memory Allocation 在C中取消引用任意内存位置 - Dereference arbitrary memory location in C C函数中任意数组类型的长度 - Length of arbitrary array type in C function 在ANSI C中键入检查任意长度数组 - Type checking arbitrary length array in ANSI C c++ - 如何检查两个任意内存范围在c/c++中没有重叠 - How to check that two arbitrary memory ranges are not overlapped in c/c++ C:如何在可用内存中放置一个任意数组? (基本) - C: How to put an arbitrary array in available memory? (basic) 是否可以检查取消引用任意内存是否会使C中的程序先验崩溃? - Is it possible to check if dereferencing arbitrary memory will crash the program apriori in C? 为什么任意键盘输入会改变 c 中的其他 memory,诅咒? - Why does arbitrary keyboard input change other memory in c, curses? 使用 C 语言中的任意类型的函数指针和任意类型的变量参数对远程嵌入式 mcu 上的任意函数进行单元测试 - unit test of arbitrary function on a remote embedded mcu using function pointers and variable arguments of arbitrary type, in C 我可以让C函数返回任意类型吗? - Can I make a C function return an arbitrary type?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM