标签: memory-layout

C中的结构内存布局

我有一个C#背景.我非常喜欢像C这样的低级语言.

在C#中,struct默认情况下由编译器布局内存.编译器可以隐式地重新排序数据字段或填充字段之间的附加位.因此,我必须指定一些特殊属性来覆盖此行为以获得精确布局.

AFAIK,C struct默认情况下不重新排序或对齐a的内存布局.但是,我听说有一个很难找到的例外.

什么是C的内存布局行为?什么应该重新订购/对齐而不是?

c struct memory-layout

76
推荐指数
3
解决办法
9万
查看次数

如何组织结构中的成员以在对齐时浪费最少的空间?

[不是结构填充和包装的重复。这个问题是关于填充的方式和时间。这是关于如何处理它的信息。]

我刚刚意识到C ++中的对齐会浪费多少内存。考虑以下简单示例:

struct X
{
    int a;
    double b;
    int c;
};

int main()
{
    cout << "sizeof(int) = "                      << sizeof(int)                      << '\n';
    cout << "sizeof(double) = "                   << sizeof(double)                   << '\n';
    cout << "2 * sizeof(int) + sizeof(double) = " << 2 * sizeof(int) + sizeof(double) << '\n';
    cout << "but sizeof(X) = "                    << sizeof(X)                        << '\n';
}
Run Code Online (Sandbox Code Playgroud)

使用g ++时,程序将提供以下输出:

sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but …
Run Code Online (Sandbox Code Playgroud)

c++ optimization memory-alignment memory-layout struct-member-alignment

54
推荐指数
4
解决办法
3273
查看次数

指针比较在 C 中如何工作?可以比较不指向同一个数组的指针吗?

在 K&R(C 编程语言第 2 版)第 5 章中,我阅读了以下内容:

首先,在某些情况下可以比较指针。如果pq指向同一个数组的成员,则关系一样==!=<>=,等正常工作。

这似乎意味着只能比较指向同一数组的指针。

但是,当我尝试此代码时

    char t = 't';
    char *pt = &t;
    char x = 'x';
    char *px = &x;

    printf("%d\n", pt > px);
Run Code Online (Sandbox Code Playgroud)

1 被打印到屏幕上。

首先,我认为我会得到 undefined 或某种类型或错误,因为ptpx没有指向同一个数组(至少在我的理解中)。

也是pt > px因为两个指针都指向存储在栈上的变量,栈向下增长,所以内存地址t大于x?为什么pt > px是真的?

当 malloc 被引入时,我变得更加困惑。 同样在第 8.7 章的 K&R 中写到以下内容:

然而,仍然存在一种假设,即sbrk可以有意义地比较指向由 返回的不同块的指针。仅允许在数组内进行指针比较的标准并不能保证这一点。因此,这个版本的malloc仅在一般指针比较有意义的机器之间是可移植的。

将指向堆上 malloced …

c pointers heap-memory memory-layout undefined-behavior

35
推荐指数
3
解决办法
5731
查看次数

struct alignment C/C++

在c/c ++中(我假设它们在这方面是相同的),如果我有以下内容:

struct S {
  T a;
  .
  .
  .
} s;
Run Code Online (Sandbox Code Playgroud)

以下是否保证是真的?

(void*)&s == (void*)&s.a;
Run Code Online (Sandbox Code Playgroud)

或者换句话说,是否有任何保证第一个成员之前没有填充?

c c++ memory-layout

31
推荐指数
2
解决办法
2779
查看次数

为什么linux二进制文件的虚拟内存地址从0x8048000开始?

在Ubuntu x86系统上反汇编ELF二进制文件我不禁注意到代码(.text)部分从虚拟地址0x8048000开始,所有较低的内存地址似乎都未使用.

这似乎相当浪费,所有谷歌出现都是涉及STACK_TOP的民间传说或防止空指针解除引用.后一种情况看起来可以通过使用单个页面来修复,而不是留下128MB的间隙.

所以我的问题是 - 对于为什么布局已经固定到这些值或者它只是一个随意的选择,有一个确定的答案吗?

linux x86 elf memory-layout

30
推荐指数
1
解决办法
4000
查看次数

当int64_t更改为int32_t时,为什么类大小会增加

在我的第一个例子中,我使用了两个位域int64_t.当我编译并获得类的大小时,我得到8.

class Test
{
    int64_t first : 40;
    int64_t second : 24;
};

int main()
{
    std::cout << sizeof(Test); // 8
}
Run Code Online (Sandbox Code Playgroud)

但是,当我将第二个bitfeild更改int32_t为类的大小时,会增加到16:

class Test
{
    int64_t first : 40;
    int32_t second : 24;
};

int main()
{
    std::cout << sizeof(Test); // 16
}
Run Code Online (Sandbox Code Playgroud)

这种情况发生在GCC 5.3.0和MSVC 2015上.但为什么呢?

c++ memory-alignment memory-layout bit-fields object-layout

28
推荐指数
4
解决办法
2174
查看次数

Rust的精确内存布局控制?

据我所知,Rust编译器允许打包,重新排序和添加填充到结构的每个字段.如果需要,我如何指定精确的内存布局?

在C#中,我有StructLayout属性,在C/C++中,我可以使用各种编译器扩展.我可以通过检查预期值位置的字节偏移来验证内存布局.

我想使用自定义着色器编写OpenGL代码,这需要精确的内存布局.有没有办法在不牺牲性能的情况下做到这一点?

memory-layout rust

23
推荐指数
2
解决办法
5042
查看次数

参考是否有存储位置?

引用是否具有存储位置,或者仅仅是另一个位置的别名?这是否因C ++版本不同而不同,或者是否与C ++的所有版本都一致?并且,如果引用具有存储位置,那么它是否只允许在类型之类的指针上使用值语义?

像这样使用参考如何工作:

struct aStruct{
   int aVariable;
   aClass& aReferencetoaClass;
};
Run Code Online (Sandbox Code Playgroud)

它会占用空间还是别名?

c++ reference memory-layout language-lawyer storage-duration

23
推荐指数
2
解决办法
817
查看次数

具有基本类型的单个数组成员的标准布局结构的保证内存布局

考虑以下简单结构:

struct A
{
    float data[16];
};
Run Code Online (Sandbox Code Playgroud)

我的问题是:

假设平台上float有32位IEEE754浮点数(如果很重要),那么C ++标准是否可以保证预期的内存布局struct A?如果不是,它将提供什么保证和/或执行保证的方式是什么?

预期存储器布局我的意思是该结构占用16*4=64在存储器字节,每个连续4字节占用由单个floatdata阵列。换句话说,预期的内存布局意味着以下测试通过:

static_assert(sizeof(A) == 16 * sizeof(float));
static_assert(offsetof(A, data[0]) == 0 * sizeof(float));
static_assert(offsetof(A, data[1]) == 1 * sizeof(float));
...
static_assert(offsetof(A, data[15]) == 15 * sizeof(float));
Run Code Online (Sandbox Code Playgroud)

offsetof这里是合法的,因为A是标准布局,请参见下文)

万一这困扰您,测试实际上会通过 gcc 9 HEAD在wandbox上通过。我从未遇到过平台和编译器的结合,它们会提供证据证明该测试可能会失败,并且我很想了解它们的存在。

为什么还要关心:

  • 类似于SSE的优化需要某些内存布局(和对齐方式,我可以在此问题中忽略它,因为可以使用标准alignas说明符来处理它)。
  • 这样的结构的序列化将简单地归结为一个不错的和可移植的write_bytes(&x, sizeof(A))
  • 一些API(例如OpenGL,特别是glUniformMatrix4fv)期望这种确切的内存布局。当然,可以仅将指针传递给data数组以传递这种类型的单个对象,但是对于其中的一系列对象(例如,用于上传矩阵类型的顶点属性),仍然需要特定的内存布局。 …

c++ memory-layout language-lawyer standard-layout

20
推荐指数
1
解决办法
713
查看次数

查找数据段的地址范围

作为一个编程练习,我在C中编写了一个标记 - 清除垃圾收集器.我希望扫描数据段(全局等)以获得指定内存的指针,但我不知道如何获取范围该段的地址.我怎么能这样做?

c garbage-collection memory-management global-variables memory-layout

19
推荐指数
2
解决办法
2万
查看次数