_stdcall與_cdecl的作用,是說明如何清空堆棧. 那堆棧里有哪些數據呢,什么時候會用到堆棧


還是不太明白這兩個函數的區別, 一個是調用者清空堆棧, 可變參數, 一個是被調用者清空堆棧,不可變參數

不知道函數怎么運行的, 所以堆棧怎么產生也不太明白, 堆棧如何產生的


// ? 這個函數有什么堆棧
void func()
{
}

// ? 這個函數堆棧又是什么樣,在函數退出時,堆棧怎么辦
void func()
{
   int a = 0 ; // 定義了一個變量, 這個變量保存在堆棧中嗎
    printf("%d" , a );
}

// ? 這個函數會不會有堆棧,怎么樣
void func()
{
   char *p = (char * ) malloc( sizeof(char)) ;
   free(p);
}

15 个解决方案

#1


_stdcall與_cdecl的作用,只對函數帶有參數起作用,與函數內部變量無關,雖然內部變量也在棧中,但釋放的時候是由函數在返回之前進行的。
http://blog.csdn.net/zhoujianhei/archive/2008/03/12/2172964.aspx

#2


_stdcall與_cdecl的作用 關於堆棧

兩種函數的局部變量是一樣的, 關鍵是參數使用棧不一樣而已

_stdcall  在函數內部釋放棧
  如匯編代碼:   __asm   ret  4;

_cdecl    需要調用函數的對象釋放棧
  如匯編代碼:   __asm   add  esp, 4

#3


http://blog.csdn.net/na_he/archive/2008/05/07/2408655.aspx
__stdcall調用約定相當於16位動態庫中經常使用的PASCAL調用約定。在32位的VC++5.0中PASCAL調用約定不再被支持(實際上它已被定義為__stdcall。除了__pascal外,__fortran和__syscall也不被支持),取而代之的是__stdcall調用約定。兩者實質上是一致的,即函數的參數自右向左通過棧傳遞,被調用的函數在返回前清理傳送參數的內存棧,但不同的是函數名的修飾部分(關於函數名的修飾部分在后面將詳細說明)。
_stdcall是Pascal程序的缺省調用方式,通常用於Win32 Api中,函數采用從右到左的壓棧方式,自己在退出時清空堆棧。VC將函數編譯后會在函數名前面加上下划線前綴,在函數名后加上"@"和參數的字節數。
2、C調用約定(即用__cdecl關鍵字說明)按從右至左的順序壓參數入棧,由調用者把參數彈出棧。對於傳送參數的內存棧是由調用者來維護的(正因為如此,實現可變參數的函數只能使用該調用約定)。另外,在函數名修飾約定方面也有所不同。
_cdecl是C和C++程序的缺省調用方式。每一個調用它的函數都包含清空堆棧的代碼,所以產生的可執行文件大小會比調用_stdcall函數的大。函數采用從右到左的壓棧方式。VC將函數編譯后會在函數名前面加上下划線前綴。是MFC缺省調用約定。

#4


傳輸傳遞用到
就是堆棧的平衡問題

#5


只有清棧的時候有區別
因此,stdcall不支持可變參數

#6


引用 1 樓 zhoujianhei 的回復:
_stdcall與_cdecl的作用,只對函數帶有參數起作用,與函數內部變量無關,雖然內部變量也在棧中,但釋放的時候是由函數在返回之前進行的。 
http://blog.csdn.net/zhoujianhei/archive/2008/03/12/2172964.aspx



_stdcall與_cdecl只是對於不同的編譯器而言的, 如果都是用VC寫的,就不需要關心, 如果用VC調用DELPHI寫的DLL, 就需要關心,因為編譯器不同

這個我明白,我想知道,堆棧是如何產生的

#7


引用 6 樓 liangzhonglin 的回復:
引用 1 樓 zhoujianhei 的回復:
_stdcall與_cdecl的作用,只對函數帶有參數起作用,與函數內部變量無關,雖然內部變量也在棧中,但釋放的時候是由函數在返回之前進行的。 
http://blog.csdn.net/zhoujianhei/archive/2008/03/12/2172964.aspx 
 


_stdcall與_cdecl只是對於不同的編譯器而言的, 如果都是用VC寫的,就不需要關心, 如果用VC調用DELPHI寫的DLL, 就需要關心,因為編譯器不同 

這個我明白,我想知道,堆棧是如何產…


如果LZ確實要把堆棧弄的很清楚,那么就要從匯編說起...

#8


stdcall與cdecl都是通過棧來傳遞參數,在調用函數時,從最右邊的參數開始,依次向左逐個push到棧中,最后call函數地址,函數中根據剛剛進入函數時esp的值來訪問這些參數,stdcall方式是在函數返回時利用ret指令清除棧中的參數,cdecl方式是函數返回后,由調用函數者修改esp的值來清除棧中的參數。

#9


要明白堆棧,必須先學匯編,搞清楚在匯編中是如何調用函數、如何參數入棧、返回值出棧、堆棧平衡。沒有這些概念,怎么跟你解釋得清楚?

#10


引用 9 樓 Mackz 的回復:
要明白堆棧,必須先學匯編,搞清楚在匯編中是如何調用函數、如何參數入棧、返回值出棧、堆棧平衡。沒有這些概念,怎么跟你解釋得清楚?


這個是不是涉及到了編譯原理,沒學過這個,所以對椎棧也就不懂了

#11


不學編譯原理也沒關系,但需要懂匯編。

#12


// ? 這個函數有什么堆棧
->棧中有函數的返回地址和EBP
void func()
{
}

// ? 這個函數堆棧又是什么樣,在函數退出時,堆棧怎么辦
->棧中有函數的返回地址、EBP和局部變量a,函數退出根據調用的方式,決定有哪個清理棧。
void func()
{
  int a = 0 ; // 定義了一個變量, 這個變量保存在堆棧中嗎
    printf("%d" , a );
}

// ? 這個函數會不會有堆棧,怎么樣
-> 當然有棧里的內容是:函數的返回地址,EBP和指針p本身的地址。
void func()
{
  char *p = (char * ) malloc( sizeof(char)) ;
  free(p);
}

#13


_cdecl為了支持可變參數而使用.

被調用者不知道有多少個參數近來了,沒法add esp,參數個數 *4
只好讓調用者負責,這導致生成的EXE的文件稍大

#14


學習了...

#15


板凳

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com