2013-06-19 1 views
5

मैंने एक printf myselef लिखा है जो va_list/va_arg/va_start/va_end/va_arg का उपयोग करता है।जीसीसी एक परियोजना को संकलित करें जो "निरस्त करने के लिए अपरिभाषित संदर्भ" दिखाता है "

typedef char *va_list; 
#define _AUPBND    (sizeof (acpi_native_int) - 1) 
#define _ADNBND    (sizeof (acpi_native_int) - 1) 
#define _bnd(X, bnd)   (((sizeof (X)) + (bnd)) & (~(bnd))) 
#define va_arg(ap, T)   (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND)))) 
#define va_end(ap)    (void) 0 
#define va_start(ap, A)   (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND)))) 

सबसे पहले, मैं लिनक्स कर्नेल से इन मैक्रो कॉपी और printf 32-बिट पूर्णांक सही मुद्रित कर सकते हैं, लेकिन 64-बिट पूर्णांक मुद्रित नहीं कर सकते और मुद्रित डबल/नाव विफल हो सकता है या collapse.Then मैं कोड की जाँच करें और मुझे लगता है कि va_ * में त्रुटियां हो सकती हैं, इसलिए मैं कर्नेल के va_ * के बजाय __builtin_va_ * का उपयोग करता हूं।

typedef __builtin_va_list va_list; 
#define va_start(v,l) __builtin_va_start(v,l) 
#define va_end(v)  __builtin_va_end(v) 
#define va_arg(v,l)  __builtin_va_arg(v,l) 

लेकिन जीसीसी शीघ्र "` बीच में बंद करें 'को अपरिभाषित संदर्भ ", तो मैं एक खाली बीच में बंद करें बारे में() और myprintf corretly काम करता है। मेरे प्रश्न हैं:

  1. क्यों लिनक्स कर्नेल के va_list/va_arg/va_start/va_end/va_argprintf 64-बिट पूर्णांक और डबल के लिए इस्तेमाल नहीं किया जा सकता है/नाव?
  2. जब मैं __builtin_va_start/__builtin_va_arg/__builtin_va_end/__builtin_va_list, क्यों जीसीसी शीघ्र "अपरिभाषित संदर्भ का इस्तेमाल किया abort'"? But I can not find the definition of को __builtin_va_ *`, उनकी परिभाषा कहाँ?
+2

के बारे में कैसे?इसके अलावा '_bnd' (_bnd OT _va_align होना माना जाता है) वहाँ में अलग ढंग से परिभाषित किया गया है:' #define __va_align (Ty) ((sizeof (Ty) + sizeof (int) - 1) और ~ (sizeof (int) - 1)) ' –

+0

@Armin के साथ सहमत हैं; आप va_arg सामान के लिए मानक शीर्षलेख का उपयोग क्यों नहीं कर रहे हैं? –

+0

@ ओली चार्ल्सवर्थ वास्तव में, हमारी परियोजना ओएस समर्थन के बिना काम कर रही है और हम मुद्रित करने के लिए साफ नियंत्रण रखते हैं, इसलिए stdio.h हमारी आवश्यकता के अनुरूप नहीं है। – Ezio

उत्तर

0

कटौती न करें और लिनक्स हेडर से पेस्ट बातें। इसके बजाय, पर इस डाल अपने स्रोत फ़ाइल के शीर्ष:

#include <stdarg.h> 

यह आप सब कुछ आप va_list और va_arg का उपयोग करने के की जरूरत है दे देंगे हालांकि, यह होगा printf में नहीं पुल या मानक के किसी भी मैं/हे stuf। एफ (जो <stdio.h> में रहता है)।

1

जीसीसी के __builtin_va_arg() जाहिरा तौर पर फोन करेगा abort() अगर यह एक प्रकार तर्क के साथ लागू किया है एक समारोह कॉल के लिए तर्क सूची के ... भाग में पारित कर दिया गया है नहीं कर सकते हैं (कम से कम कुछ प्लेटफॉर्म या स्थितियों पर)।

उदाहरण के लिए, ऐसे विज्ञापन जो char या float इस तरह के एक तर्क के रूप में पारित होने के कारण int या double करने के लिए प्रोत्साहित किया गया होगा। va_arg(ap,char) या va_arg(ap,float) के रूप में उन तर्कों तक पहुंचने के लिए अपरिभाषित व्यवहार है और जीसीसी उस स्थिति में abort() पर कॉल कर सकता है - या यह कुछ और कर सकता है (मेरा मिनजीडब्ल्यू कंपाइलर क्रैश के कारण एक अवैध निर्देश निष्पादित करेगा)।

आप जब संकलित कुछ इस तरह देख सकते हैं:

In file included from D:\temp\test.c:2:0: 
D:\temp\test.c: In function 'foo': 
D:\temp\test.c:12:16: warning: 'char' is promoted to 'int' when passed through '...' [enabled by default] 
    c = va_arg(ap,char); 
       ^
D:\temp\test.c:12:16: note: (so you should pass 'int' not 'char' to 'va_arg') 
D:\temp\test.c:12:16: note: if this code is reached, the program will abort 

__builtin_va_* की 'परिभाषा' संकलक में संकलित किया गया है (यही कारण है कि 'builtin' है नाम का हिस्सा है)।

जहां तक ​​लिनक्स मैक्रोज़ वर्रग्स एक्सेस के लिए है: जबकि लिनक्स कर्नेल हेडर से ली गई परिभाषाएं/एसीपीआई/प्लेटफ़ॉर्म/एसीएनवीएचएच में मौजूद हैं, यदि आप सशर्त संकलन पर ध्यान से देखते हैं, तो आप ' देखेंगे कि लिनक्स कर्नेल का निर्माण करते समय उन मैक्रोज़ का उपयोग नहीं किया जाता है। मुझे बिल्कुल यकीन नहीं है कि जब मैक्रोज़ प्रभावी हैं, लेकिन वे x64/x86-64/amd64 बिल्ड के साथ काम नहीं करेंगे क्योंकि उस प्लेटफ़ॉर्म पर एबीआई पूरी तरह से स्टैक-आधारित नहीं है। विवरण के लिए "सिस्टम वी एप्लीकेशन बाइनरी इंटरफेस - एएमडी 64 आर्किटेक्चर प्रोसेसर सप्लीमेंट" की धारा 3.5.6 देखें।

संबंधित मुद्दे