2012-10-13 16 views
5

tôi có chức năng: foo()vấn đề #define nếu gọi nó từ bên trong một if() chặn

Tôi muốn viết một #define để đặt 'trước mặt' của foo() (một shim tôi đoán) để thêm debug vào phía trước của foo(). Vì vậy, các #define nên nhìn này này:

#define foo(dev) {       \ 
     printk("%s: get %lx\n", (dev)->name); \ 
     foo_orig(dev);       \ 
    } 

Và sau đó tôi đổi tên foo()-foo_orig().

này hoạt động OK nếu foo() hàm được gọi trong 'cách ly' như thế này:

foo(dev); 

NHƯNG, nếu gọi của nó trong vòng một if() sau đó nó là một vấn đề biên dịch ...

if (something() && foo(dev)) { 
    .. 

Tôi đã giải thích vấn đề chưa? và có một giải pháp cho điều này?

Vấn đề là tôi thực sự cần shim như xác định bởi vì tôi cần mã để sống trong chức năng gọi thay vì foo(). [Lý do cho điều này là bởi vì tôi cần phải đổ ra EIP các chức năng gọi điện thoại vì lý do debug (tức là tôi cần phải biết ai đang gọi foo()]

+1

Tại sao không làm một chức năng thay vì một vĩ mô mà các cuộc gọi printk và sau đó trả về giá trị của foo_orig? – PherricOxide

+0

Không chắc chắn bạn sử dụng trình biên dịch nào nhưng bạn sẽ có thể mở rộng các chỉ thị tiền xử lý và xem mã mà trình biên dịch thấy (và không thích) sau khi mở rộng –

Trả lời

2

AFAIK toán tử phẩy nên làm việc:.

#define foo(dev) (printk("%s: get %lx\n", (dev)->name), foo_orig(dev)) 
+0

Tại sao lại là downvote? – Pubby

+0

+1 Điều này sẽ hoạt động, giả sử rằng 'printk' không phải là' void'. – dasblinkenlight

+0

@dasblinkenlight Tôi đang biên dịch tốt nếu biểu thức dấu phẩy bên trái là 'void'. Có lẽ suy nghĩ của bạn về các đối số chức năng? – Pubby

-1

lý do cho điều này là b/ci cần phải đổ ra EIP các chức năng gọi điện thoại vì lý do debug (tức là tôi cần phải biết ai đang gọi foo()

Vâng, bạn chỉ có thể viết một số lắp ráp để tra cứu địa chỉ trả lại điện tử trên ngăn xếp; nhưng trên thực tế, hầu hết các trình biên dịch đã được xây dựng để giải quyết nhu cầu này; xem here cho GCC (đối với Clang nó giống nhau), here cho VC++ (và trên trình biên dịch Intel, nó giống nhau).

Chỉ cần viết shim của bạn bên trong foo thực và sử dụng _ReturnAddress()/__builtin_return_address(0) để nhận địa chỉ trả về của hàm (ví dụ: một lệnh sau lệnh call đã bắt đầu chức năng).

+0

Sự cố không nhận được địa chỉ ... 'printk' sẽ hoạt động tốt. –

0

#define giống như thực hiện tìm kiếm và thay thế. Vì vậy, câu lệnh 'if' của bạn trở thành như sau tại thời gian biên dịch:

if (something() && { print(....); foo_orig(dev);}) { 
} 

Điều đó sẽ giải thích lỗi trình biên dịch.

+0

Tại sao điều này lại bị giảm? Nó không sai. – rmaddy

1

tôi giả sử bạn đang sử dụng GCC, thì đây sẽ giúp:

#define foo(dev) ({       \ 
     printk("%s: get %lx\n", (dev)->name); \ 
     foo_orig(dev);       \ 
    }) 

Điểm mấu chốt là ngoặc xung quanh dấu ngoặc nhọn.

GCC: Statements and Declarations in Expressions

0

Sử dụng toán tử dấu phẩy:

#define foo(dev) (printk(blah, blah), foo_orig(dev)) 

Với C99 bạn có thể sử dụng một chức năng inline

static inline rtype foo (type *dev) { printk(blah, blah); return foo_orig(dev); } 
0

Có lẽ thay thế các dấu chấm phẩy ; trong #define của bạn bằng dấu phẩy ,, và tháo niềng răng/ngoặc vuông {}.

Hoặc trong câu hỏi if, thay thế foo(dev) bằng (foo)(dev).

+0

và giá trị trả về là gì? –

+1

@Thomas Berger: Giá trị trả về của toán tử dấu phẩy là RHS. –

+0

phải, thx đến muộn ở đây quá;) –

1

Vấn đề là cách hoạt động của #define.

Ở giai đoạn tiền xử lý, trình biên dịch sẽ thay thế bất kỳ sự xuất hiện nào của foo bằng văn bản được xác định. Vì vậy, mã của bạn sẽ trông như thế này:

// call to foo() -> valid 
    printk("%s: get %lx\n", (dev)->name); 
    foo_orig(dev);  

    // within a parenthesis - invalid 
    if (something() && printk("%s: get %lx\n", (dev)->name); 
      foo_orig(dev);) { 

Một giải pháp sẽ được sử dụng một chức năng thực sự cho gỡ lỗi, như thế này

foo_dbg(type *dev) { 
    printk("%s: get %lx\n", (dev)->name); 
    return foo_orig(dev); 
} 
#ifdef DEBUG 
    #define foo(dev) foo_dbg(dev) 
#else 
    #define foo(dev) foo_orig(dev) 
#endif 
Các vấn đề liên quan