亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区
Chinaunix
標題:
還是乖乖的用va_arg()吧
[打印本頁]
作者:
karma303
時間:
2017-06-05 23:43
標題:
還是乖乖的用va_arg()吧
本帖最后由 karma303 于 2017-06-05 23:47 編輯
我之前實現(xiàn)可變參數(shù)的函數(shù),像void foobar( sdf, ...),都是用很土的方式:
unsigned *parg = &sdf;。ɑ蚴莿e的什么類型,一般都因地制宜)
然后parg[1], parg[2]...一個個來訪問。 也沒出過什么差錯。
今天終于遭報應了,一個bug調(diào)了至少有4個小時。
簡單點兒說,就是foobar的堆棧布局,不再是我想象的那樣經(jīng)典的C堆棧布局:
|__sdf __|
|_arg1__|
|_arg2__|
|___.____|
復制代碼
是跟蹤了跟蹤了匯編碼才發(fā)現(xiàn),foobar的調(diào)用代碼,還是經(jīng)典的C參數(shù)入棧的方式,但進入foobar之后,gcc做了一些處理,例如把sdf復制到新的棧幀,等等?傊畬е聅df下方不再是__VA_ARGS__了。導致只能用va_start/va_arg/va_end來訪問。
最后把今天這段出bug的代碼貼上吧(好像沒必要,不過還是貼上吧)。
void __tprobe(struct timeval *base, struct timeval *last, ...){
long *interval, *gone;
struct timeval now;
gettimeofday(&now, 0);
va_list vp;
va_start(vp, last);
interval = va_arg(vp, long *);
if(interval){
*interval = (now.tv_sec - last->tv_sec) * 1000000+
now.tv_usec - last->tv_usec;
gone = va_arg(vp, long *);
if(gone){
*gone = (now.tv_sec - base->tv_sec)*1000000+
now.tv_usec - base->tv_usec;
}
}
va_end(vp);
*last = now;
}
復制代碼
#include<sys/time.h>
#define TSTAMP_INIT()\
struct timeval __tm_base;\
struct timeval __tm_last;\
gettimeofday(&__tm_base, 0)
/* call like this:
* TSTAMP() just make a timestamp. do nothing else.
* TSTAMP(interval) make timestamp, and query interval to the latest TSTAMP()
* TSTAMP(interval, gone) and query how many useconds had gone since TSTAMP_INIT
*
* The arguments @interval, @gone should be a (long *)pointer for storing result
*/
#define TSTAMP(...)\
__tprobe(&__tm_base, &__tm_last,##__VA_ARGS__ ,0)
復制代碼
之前一直不愿意用va_arg(),一是學不會,二是是想鍛煉自己多動手,F(xiàn)在好了,終于死心了。
作者:
superwujc
時間:
2017-06-08 12:55
樓主很給力哈
作者:
qianguozheng
時間:
2017-06-13 11:40
出錯的代碼呢? 帖的是正確的吧
歡迎光臨 Chinaunix (http://72891.cn/)
Powered by Discuz! X3.2