使用malloc进行堆栈对齐

时间:2013-03-31 05:14:56

标签: c stack malloc

我正在实现一个用户级线程库作为赋值。内存分配在原始代码本身中完成。但似乎很难理解代码中发生了什么。任何人都可以帮我解释一下。

void * malloc_stack() 
{
  /* allocate something aligned at 16
   */
   void *ptr = malloc(STACK_SIZE + 16);
   if (!ptr) return NULL;
   ptr = (void *)(((int)ptr & (-1 << 4)) + 0x10);
   return ptr;
}

编辑:因为堆栈向下增长,分配给ptr的地址是什么?它是堆栈的基础还是堆栈的顶部?

假设基数位于更高的内存地址,而顶部位于较低的内存地址(因为向下增长)

3 个答案:

答案 0 :(得分:0)

这看起来像aligned_malloc的实现,当您拥有处理器(或协处理器或支持DMA的设备)时,某些或所有指令(操作)只能在对齐的内存上工作,这非常有用。除了在未对齐的内存上完全失败的指令外,对齐可能会影响原子性。

它与堆栈无关。就其本质而言,动态分配不能来自堆栈,因为堆栈上的分配不会返回到调用函数,但动态分配必须一直存在,直到匹配的释放调用。

(换句话说:根据定义,Last-In-First-Out是一个堆栈。动态分配不是LIFO,但可以适应生命周期的任意排序。)

答案 1 :(得分:0)

  

我正在实现一个用户级线程库作为赋值。该   内存分配在原始代码本身中完成。但似乎很难   了解代码中发生了什么。任何人都可以帮助我   解释

不确定。 C标准说: E1的结果&lt;&lt; E2是E1左移E2位位置;腾出的位用零填充。如果E1具有无符号类型,则{无关省略}。如果E1具有有符号类型和非负值,并且在结果类型中可以表示E1×2E2,那么这就是结果值;否则,行为未定义。

因此,-1 << 4是未定义的行为。以下是C标准对未定义行为的解释:行为,使用不可移植或错误的程序结构或错误数据时,本国际标准没有要求

因此,此代码没有要求。它既可以做任何事情,也可以做任何事情,它不需要任何理由或逻辑。它可以依靠 faery灰尘传感器来正确操作,我们所知道的......

  

编辑:因为堆栈向下增长,所分配的地址是多少   到ptr? ...

什么堆栈?这不是一个地址,因为它不能保证指向一个对象;像处理它一样对待它也是未定义的行为:如果左值在评估时没有指定对象,则行为是未定义的。

下一个问题:

  

...它是堆栈的基础还是堆栈的顶部?

它既可以是任何东西,也不是任何东西(包括具有高度传染性的癌症尘埃)。未定义的行为......

  

假设基数位于更高的内存地址且顶部位于   较低的内存地址(因为向下增长)

......会很傻。未定义的行为......

对于您的配置,此代码可能在您的系统上正常运行,但如果使用不同的操作系统,硬件,C标准库或编译器可能会出现故障。 C的设计并不仅仅与您的系统兼容,而是与各种各样的系统兼容; C代码不应该这样写! C的设计使程序可以移植或独立于OS,硬件,C标准库和编译器实现编写!你正在读哪本书?

答案 2 :(得分:-1)

因此,如果我正确理解了这个问题,您需要帮助理解此代码

我将假设你理解函数的前两行以及最后一行,所以只留下

ptr = (void *)(((int)ptr & (-1 << 4)) + 0x10);

首先我们应该看看(-1 << 4)。自从你转换ptr以来我认为可以安全地假设-1也将被视为一个int并且将成为值0xFFFFFFFF(这将假设你的系统&int; int有4个字节或32位,我认为现在这是一个非常普遍的事情。接下来,因为我们应该看一下这样的二进制表示,所以-1 = 0xFFFFFFFF = 0b11111111111111111111111111111111所以移位4 ... (-1 << 4) = 0b11111111111111111111111111110000 = 0xFFFFFFF0

下一个ptr正在接受此值,这意味着ptr将被强制结束0000。请注意,在使用此格式转换任何类型的数字时,它将被16整除,从而将ptr16对齐。然后它添加0x10以强制地址在分配的区域内。

希望这有帮助!

编辑:因为堆栈向下增长,分配给ptr的地址是什么?它是堆栈的基础还是堆栈的顶部?

假设基数位于更高的内存地址,而顶部位于较低的内存地址(因为向下增长)

正如评论中指出的那样:这种行为非常不明确。如果这是用于家庭作业,我怀疑它是,我建议您验证这是您的机器的行为(并且可能是正在评分它的机器正在打开)。否则要修复它,你可以简单地用-1替换0xFFFFFFFF,然后我相信问题应该得到解决(我再也没有参考c标准,这只是从经验的角度来看)。请注意,将-1替换为0xFFFFFFFFu,我所解释的内容仍然有意义。