我试图从C#调用Delphi DLL中的过程.该过程期望调用者预分配并输入一个array of array of TSomeRecord,然后它将操作TSomeRecord元素作为返回结果的方法.因此,我需要手工制作Delphi数组的动态数组.
现在,我在这里发现动态array of X由指向动态数组的第一个元素的指针组成,并且第一个元素具有引用计数和长度前面的数组(两个32位整数)的元素数(元素数),以及元素内联和连续存储,以便整个内存在内存中看起来像这样:  
rrrrllll000...000111...12...
        ^
rrrr是引用计数,llll是长度,0123是元素,^是指针指向的位置.这证明了; 我测试了它,它的工作原理.
多维动态数组我假定我可以替代array of Y为X在array of X,换言之,所述外尺寸是简单地(指针)动态数组,像这样的一个动态数组:  
rrrrllll000011112222...
        ^
其中元素0000,1111等现在是独立分配的动态数组的32位指针.但是,这样做会让我遇到麻烦的访问权限.这显然不是德尔福希望我这样做的方式.任何人都可以向我解释我是如何我该怎么办呢?
我编写了几个程序,发现当在64位编译时,内存映射段(例如共享对象和共享内存保存)总是位于7f9aca84a000-7fff88400000左右但从未完全相同.
我想知道x86_64架构(ELF64)上的内存段是否有固定的起始地址,或者该段的最大和最小范围是多少?
这就是为什么我问这个问题.我们正在将系统从Tru64 UNIX迁移到Linux.该系统使用IPC Sys V共享内存的复杂固定内存映射,并使用链表在该段内从结构转到另一个.由于这段代码的大小和复杂性,以及我们手头有限的时间,我们正在尝试找到一种可靠的方法来修复共享内存的开始(有效地使用带有指定地址的shmat来附加段).对于64位,虚拟地址空间是如此巨大(48位有效可能的地址),选择"安全"固定地址比32位更容易,风险更小.
我正在定义要通过不同设备和不同编程语言之间的通信通道接收和发送的结构.为此,我使用StructLayoutAttribute(顺序,pack = 1 - 在重要的情况下)在内存中明确定义它们的布局.
从文档中,我知道当struct只包含字段时它可以工作.它似乎也适用于'简单'属性(使用空get; set;).但是我不知道是不是总是如此.
所以我关于StructLayoutAttribute对属性的影响的问题分为两个:
是否存在与指针具有相同大小和对齐的整数类型?
有std::intptr_t和std::uintptr_t,但我相信它们没有与指针本身相同的对齐方式.
我正在用 iOS 版 Metal 制作一个小游戏。在我的一个内核着色器中(在我的 .metal 文件中)。我正在定义一个结构来保存游戏部分的一些元数据。
该结构如下所示:
struct ColorSetup {
    float4 color;
    float4 degradationColor;
    float degradationRate;
};
这工作得很好,但是当我尝试向结构中添加更多字段时,例如:
struct ColorSetup {
    float4 color;
    float4 degradationColor;
    float4 threshholdColor;
    float degradationRate;
};
该代码行为不当,似乎无法使用某些字段。此时新字段尚未被使用。我的第一个想法是它与结构的内存对齐有关。我的印象是编译器会添加正确的填充,但仍然继续尝试自己正确调整结构的大小(按降序排列字段并将结构对齐到 48 和 64 字节),但没有任何成功。我还尝试使用打包数据类型来避免对齐问题,但仍然没有成功。
我知道逻辑是正确的,因为我在不使用结构的情况下编写了相同的逻辑,然后将其移植到使用结构来保存具有完全相同行为的数据。但此时添加任何字段都会破坏它。此外,保留原始结构但使用打包数据类型也会以类似的方式破坏它。
struct ColorSetup {
    packed_float4 color;
    packed_float4 degradationColor;
    float degradationRate;
};
所以这看起来肯定是一个内存布局问题,但我不清楚如何在不解决该问题的情况下解决它。
我可以尝试什么想法或想法吗?
编辑:
数据不会通过 MTLBuffer 传递到我的计算着色器中,而是简单地在 .metal 文件中内联的常量内存空间中定义,如下所示:
constant ColorSetup redColor = {
    .color = red,
    .degradationColor = white,
    .degradationRate = 0.0035
};
编辑2:
尝试描述更多发现以及代码实际执行的操作。
所讨论的中断函数是一种根据该结构中提供的值来淡化颜色的方法。
float4 degrade(float4 color, ColorSetup colorSetup, ColorLimit colorLimit) …快速而简单的问题:std::bitset保证在内存中是连续的吗?
我知道它遵守CopyConstructible和CopyAssignable概念,但是它也是一个ContiguousContainer(或类似的东西)std::vector吗?
除了填充之外,我还想在这样的结构上进行按位运算:
struct tmp
{
    std::bitset<32> b;
    unsigned int    c;
};
因此,连续性b非常重要.当然,这会导致知道if是否std::bitset是标准布局类,以便每个按位操作都有效.
我对 Linux 中程序的内存布局有一些疑问。我从各种来源(我正在阅读“从头开始编程”)知道每个部分都被加载到它自己的内存区域中。文本部分首先在虚拟地址 0x8048000 处加载,紧接着加载数据部分,接下来是 bss 部分,然后是堆和堆栈。
\n\n为了试验布局,我用汇编语言编写了这个程序。首先它打印一些标签的地址并计算系统断点。然后就进入无限循环了。循环递增一个指针,然后尝试访问该地址处的内存,在某个时刻,分段错误将退出程序(我是故意这样做的)。
\n\n这是程序:
\n\n.section .data\n\nstart_data:\nstr_mem_access:\n.ascii "Accessing address: 0x%x\\n\\0"\nstr_data_start:\n.ascii "Data section start at: 0x%x\\n\\0"\nstr_data_end:\n.ascii "Data section ends at: 0x%x\\n\\0"\nstr_bss_start:\n.ascii "bss section starts at: 0x%x\\n\\0"\nstr_bss_end:\n.ascii "bss section ends at: 0x%x\\n\\0"\nstr_text_start:\n.ascii "text section starts at: 0x%x\\n\\0"\nstr_text_end:\n.ascii "text section ends at: 0x%x\\n\\0"\nstr_break:\n.ascii "break at: 0x%x\\n\\0"\nend_data:\n\n.section .bss\n\nstart_bss:\n.lcomm buffer, 500\n.lcomm buffer2, 250\nend_bss:\n\n.section .text\nstart_text:\n\n.globl _start\n_start:\n\n# print address of start_text label\npushl $start_text\npushl $str_text_start\ncall printf\naddl $8, %esp\n# print address of end_text label\npushl $end_text\npushl $str_text_end\ncall printf\naddl $8, %esp\n# print address of …我正在学习可执行二进制文件的布局。我的最终目标是分析可以重构(在其源代码中)以减少编译输出大小的特定可执行文件。
我一直在使用https://www.embeddedrelated.com/showarticle/900.php和https://www.geeksforgeeks.org/memory-layout-of-c-program/作为这个初步学习的参考。
据我所知,链接器脚本指定了放置已编译二进制文件部分的地址。例如
> ld --verbose | grep text
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
我认为这意味着text编译二进制文件的段从内存地址开始0x400000- 真的吗?
这个值0x400000代表什么?我可能没有正确理解某些东西,但肯定0x400000不代表物理内存位置,是吗?例如,如果我跑我的编译的两个实例a.out可并行执行,他们不可能都同时占据的空间0x400000,对不对?
ndarray大多数时候使用 numpy s 我们不需要担心我们漂亮的小脑袋关于内存布局,因为结果不依赖于它。
除非他们这样做。例如,考虑这种设置 3x2 矩阵对角线的稍微过度设计的方法
>>> a = np.zeros((3,2))
>>> a.reshape(2,3)[:,0] = 1
>>> a
array([[1., 0.],
       [0., 1.],
       [0., 0.]])
只要我们控制好内存布局a就可以了。但是,如果我们不这样做,那就是一个错误,更糟糕的是,这是一个令人讨厌的无声错误:
>>> a = np.zeros((3,2),order='F')
>>> a.reshape(2,3)[:,0] = 1
>>> a
array([[0., 0.],
       [0., 0.],
       [0., 0.]])
这足以表明内存布局不仅仅是一个实现细节。
为了了解数组布局,人们可能合理地要求的第一件事是新数组是什么样的?这些工厂empty,ones,zeros,identity每默认等回报C-连续布局。
但是,此规则并未扩展到 numpy 分配的每个新数组。例如:
>>> a = np.arange(8).reshape(2,2,2).transpose(1,0,2)
>>> aa = a*a
乘积aa是 ufunc 分配的新数组np.multiply。它是 C 连续的吗?不:
>>> aa.strides
(16, 32, 8)
我的猜测是,这是优化的结果,该优化认识到可以在平面线性阵列上完成此操作,这将解释为什么输出具有与输入相同的内存布局。
事实上,这甚至很有用,不像下面的废话函数。它显示了一个方便的习惯用法来实现轴参数,同时仍然保持索引简单。 …
目前,我正在学习记忆布局C.现在我知道在C程序的内存存在几个部分:text,data,bss,heap和stack。他们还说heap是与程序之外的其他东西共享。
我的问题是这些。
heap共享到底是什么?一个源指出堆必须始终以使其可用于被释放的其它过程而另一个表示堆区由所有线程,共享库,并且动态加载的模块共享的过程。如果它不与其他进程共享,我真的必须在我的程序运行时(不是在程序结束时)释放它吗?