为什么一些函数参数存储在堆栈上,一些存储在堆上?

时间:2014-07-18 12:28:36

标签: python debugging

我正在阅读" Gray Hat Python"。本书讲授调试技术,您可以通过调试器更改变量值。

在下面的代码中,作者教我们如何更改counter变量值。但是我想做更多,所以我将'Hello'参数添加到printf函数中,以便我可以将其更改为'Bye'之类的其他内容。

我通过调试器发现的是'Hello'存储在堆中。存储'Hello'的堆中的地址保存在堆栈中;为什么呢?

我的问题是:基于存储在堆栈上的一些参数和堆上的一些参数是什么?

from ctypes import *
import time

msvcrt = cdll.msvcrt
counter = 99999999

while 1:
    msvcrt.printf("Loop iteration %d!\n" , counter, "Hello")
    time.sleep(2)
    counter += 1

1 个答案:

答案 0 :(得分:2)

这些内容在calling conventionsABI的一部分)中定义。调用约定定义了一些内容,例如:

  • 其中(堆栈或注册)以及如何(在单个单元格中,分布在多个单元格上,引用堆)来存储参数,
  • 存储参数的顺序(从左到右或从右到左)
  • 谁负责在通话后调用堆栈(来电者或被叫者),
  • 应保留哪些寄存器。

多年来,对于32位x86处理器(名称为cdeclstdcallfastcall),使用了一堆略有不同的调用约定。对于64位x86处理器,基本上有only two calling conventions(一个用于Microsoft,一个用于地球上的其他人)。

在32位Windows上,printf使用cdecl约定。在64位Windows上,printf使用Microsoft的64位ABI中的调用约定。

有关调用约定的更多信息可以在this answer中找到。