2009-06-08 14 views
26

मेरे आवेदन में संभावित रूप से बड़ी संख्या में तर्क पारित किए गए हैं और मैं फ़िल्टर की सूची में तर्कों को डुप्लिकेट करने के हिट की स्मृति से बचना चाहता हूं। मैं उन्हें जगह में फ़िल्टर करना चाहता हूं लेकिन मुझे पूरा यकीन है कि argv सरणी के साथ गड़बड़ाना, या जो भी डेटा इंगित करता है, शायद यह सलाह नहीं दी जाती है। कोई सुझाव?क्या argv को बदलना संभव है या क्या मुझे इसकी एक समायोजित प्रति बनाने की आवश्यकता है?

+0

यह ध्यान देने योग्य है कि कुछ ओएस की तर्कों की संख्या (Win32 पर 32k पर) की सीमा है। मैं डेस्कटॉप ऐप पर 32kb अधिक हिट पर विचार नहीं करता, लेकिन जाहिर है YMMV –

+0

क्षमा करें YMMV? यह मुझ पर एक नया है ... – ojblass

+0

आपका मील का मैदान भिन्न हो सकता है? – ojblass

उत्तर

23

एक बार argv मुख्य विधि में पारित किया गया है, तो आप इसे किसी अन्य सी सरणी की तरह व्यवहार कर सकते हैं - जगह में इसे बदलने के रूप में आप की तरह, सिर्फ तुम क्या इसके साथ क्या कर रहे हैं के बारे में पता होना। सरणी की सामग्री को कोड में इसके साथ स्पष्ट रूप से किए गए कार्यों के अलावा रिटर्न कोड या प्रोग्राम के निष्पादन पर कोई प्रभाव नहीं पड़ता है। मैं किसी भी कारण से नहीं सोच सकता कि यह विशेष रूप से इलाज के लिए "सलाह दी जा सकती" है।

बेशक, आपको अभी भी आकस्मिक रूप से Argv की सीमाओं से परे स्मृति तक पहुंचने की परवाह करने की आवश्यकता है। इसका सामान्य फ्लिप एक सामान्य सी सरणी की तरह पहुंच योग्य होता है कि यह किसी अन्य सामान्य सी सरणी की तरह त्रुटियों तक पहुंचने का भी प्रवण होता है। (सभी को धन्यवाद जो टिप्पणियों और अन्य प्रतिक्रियाओं में इस ने बताया!)

+0

धन्यवाद। मुझे यकीन नहीं है कि मैंने सोचा था कि स्मृति विशेष थी। – ojblass

+1

तत्व कहीं और आवंटित किसी भी अन्य तार की तरह हैं, निश्चित रूप से, सुनिश्चित करें कि उनके अंत में नहीं चलना चाहिए। आप नहीं जानते कि वहां क्या है। – dmckee

+0

ध्यान दें कि (लिनक्स पर, कम से कम) आप पीएस से पासवर्ड छिपाने के लिए 'argv' की सामग्री को ओवरराइट कर सकते हैं: http://unix.stackexchange.com/a/88679/27530 – user3364825

4

अनुभव से, इस तरह के जीएनयू getopt() समस्याओं के कारण के बिना तर्क सूची दूसरे स्थान पर रखना के रूप में कार्य करता है। जैसा कि @ टिम कहते हैं, जब तक आप समझदारी से खेलते हैं, आप पॉइंटर्स की सरणी और यहां तक ​​कि व्यक्तिगत तारों का उपयोग कर सकते हैं। बस किसी भी अंतर्निहित सरणी सीमाओं को खत्म न करें।

+0

ठीक है धन्यवाद। मुझे यकीन नहीं है कि मैंने सोचा था कि स्मृति विशेष थी। मुझे पहले ऐसा करने की ज़रूरत नहीं थी। – ojblass

1

एकमात्र बार मैं कहूंगा कि सीधे एआरवीवी में हेरफेर करना खराब विचार होगा जब कोई अनुप्रयोग argv [0] की सामग्री के आधार पर अपना व्यवहार बदलता है।

हालांकि, argv [0] के आधार पर एक प्रोग्राम के व्यवहार को बदलना एक बहुत ही खराब विचार है जहां पोर्टेबिलिटी चिंता का विषय है।

इसके अलावा, आप इसका इलाज कर सकते हैं जैसे कि आप किसी अन्य सरणी की तरह। के रूप में जोनाथन ने कहा, जीएनयू getopt() तर्क सूची permutes गैर विध्वंस, मैं अन्य getopt() कार्यान्वयन कि जहां तक ​​जाना serializing और यहां तक ​​कि बहस hashing (उपयोगी है जब एक प्रोग्राम ARG_MAX के पास आता है) के रूप में देखा है।

बस अपने सूचक अंकगणित से सावधान रहें।

+1

कुछ ग़लत चाल हैं जहां कार्यक्रम किसी अन्य कार्यक्रम के लिए पासथ्रू हो सकते हैं और मैंने Argv [0] के सभी प्रकार के भयानक जोड़ों को देखा है। मेरे मामले में मैं कुछ तर्कों को खाली कर दूंगा (उन्हें खाली खाली समाप्त स्ट्रिंग पर सेट कर रहा हूं) ताकि उनका पुनरीक्षण नहीं किया जा सके। मेरे विशेष परिस्थिति में मेमोरी अधिक महत्वपूर्ण है और मुझे पता है कि उचित डेटा संरचना बनाना बेहतर है। आपके सहयोग के लिए धन्यवाद! – ojblass

+0

@ojblass उस स्थिति में, मैं सिर्फ एक हैश तालिका का निर्माण करूंगा जिसमें उनमें 'अवांछित' तर्क हैं, उन्हें दाईं ओर ले जाएं और (अंत में) उन्हें स्निप करें। मुझे एक ऐसे उपकरण पर लगभग एक ही समस्या थी जिसमें बहुत ही जटिल एलसीडी नियंत्रक था जहां ग्राहक एक ओवर-सरलीकृत सीएलआई प्रोग्राम का उपयोग करके/इसे पढ़ने के लिए उपयोग कर रहा था। मेरे पास काम करने के लिए लगभग 8 एमबी था, इसलिए मैं बचत की आवश्यकता को समझता हूं। –

5

सी मानक (N1256) के नवीनतम मसौदे में कहा गया है वहाँ main समारोह के दो अनुमति रूपों हैं कि:

int main (void); 
int main (int argc, char* argv[]); 

लेकिन जड़ खंड "या कुछ अन्य कार्यान्वयन से परिभाषित तरीके में है।" ऐसा लगता है कि मुझे अर्ध ट्रेलर के माध्यम से चलाने के लिए पर्याप्त मानक में एक छेड़छाड़ की बात है।

तर्कों में बदलावों को अस्वीकार करने के लिए argv के लिए कुछ लोग विशेष रूप से "const char *" का उपयोग करते हैं।

pax> cat qq.c 
#include <stdio.h> 
int main (int c, const char *v[]) { 
    *v[1] = 'X'; 
    printf ("[%s]\n", v[1]); 
    return 0; 
} 

pax> gcc -o qq qq.c 
qq.c: In function `main': 
qq.c:3: error: assignment of read-only location 

हालांकि, अगर आप "const" निकालने के लिए, यह ठीक काम करता है: अपने मुख्य कार्य इस तरह से परिभाषित किया गया है, तो आप अक्षर हैं जो argv[] अंक के लिए, के रूप में निम्नलिखित कार्यक्रम इसका सबूत बदलने के लिए अनुमति नहीं है

pax> cat qq2.c 
#include <stdio.h> 
int main (int c, char *v[]) { 
    *v[1] = 'X'; 
    printf ("[%s]\n", v[1]); 
    return 0; 
} 

pax> gcc -o qq2 qq2.c ; ./qq2 
[Xello] 

मुझे लगता है कि यह भी सी ++ के लिए मामला है।वर्तमान मसौदा कहता है:

All implementations shall allow both of the following definitions of main: 
    int main(); 
    int main(int argc, char* argv[]); 

लेकिन यह विशेष रूप से अन्य वेरिएंट नामंज़ूर नहीं करता है तो आप शायद सी में एक "const" संस्करण को स्वीकार कर सकता है ++ के साथ-साथ (और, वास्तव में, जी ++ करता है)।

केवल एक चीज जिसे आप सावधान रहना चाहते हैं, किसी भी तत्व के आकार को बढ़ाने की कोशिश कर रहा है। मानक जनादेश नहीं हैं कि वे कैसे संग्रहीत किए जाते हैं ताकि एक तर्क का विस्तार हो सकता है (संभवतः) दूसरों को प्रभावित कर सकता है, या कुछ अन्य असंबंधित डेटा।

59

C99 मानक इस argv (और argc) संशोधित करने के बारे कहते हैं:

मापदंडों argc और argv और तार करने के लिए द्वारा argv सरणी कार्यक्रम द्वारा परिवर्तनीय होंगे, और बनाए रखने बताया उन्होंने अपनी पिछली संग्रहीत प्रोग्राम स्टार्टअप और प्रोग्राम समाप्ति के बीच मूल्य।

+31

मैं उन लोगों की प्रशंसा करता हूं जो मानक के माध्यम से कुशलता से खोज सकते हैं। – ojblass

2

ऑपरेटिंग सिस्टम इसे निष्पादित करने से पहले आवेदक स्टैक में argv और argc को दबाता है, और आप उन्हें किसी अन्य स्टैक चर के समान व्यवहार कर सकते हैं।

0

argv का मूल आवंटन एक कंपाइलर/रनटाइम पसंद के रूप में छोड़ा गया है। तो इसे संशोधित करने के लिए सुरक्षित नहीं है। कई प्रणालियां इसे ढेर पर बनाती हैं, इसलिए मुख्य रिटर्न के दौरान ऑटो-डिलीओकेट किया जाता है। अन्य इसे ढेर पर बनाते हैं, और मुख्य रिटर्न के दौरान इसे मुक्त करते हैं (या नहीं)।

एक तर्क के मूल्य को बदलने के लिए सुरक्षित है, जब तक कि आप इसे अधिक लंबा बनाने की कोशिश न करें (बफर ओवररन त्रुटि)। तर्कों के क्रम को घुमाने के लिए सुरक्षित है।

करने के लिए तर्क आप preprocessed किया है निकालने के लिए, कुछ इस तरह काम करेगा:

(त्रुटि की स्थिति नहीं के लिए जाँच की बहुत सारी, "--विशेष" अन्य है कि पहली आर्ग के लिए चेक नहीं किया गया, आदि यह, सब के बाद सिर्फ एक डेमो के-अवधारणा है,)

int main(int argc, char** argv) 
{ 
    bool doSpecial = false; // an assumption 
    if (0 == strcmp(argv[1], "--special")) 
    { 
     doSpecial = true; // no longer an assumption 
     // remove the "--special" argument 
     // but do copy the NULL at the end. 
     for(int i=1; i<argc; ++i) 
      argv[i] = argv[i+1]; 
     --argc; 
    } 
    // all normal processing with "--special" removed. 
    // the doSpecial flag is available if wanted. 
    return 0; 
} 

लेकिन पूर्ण हेरफेर के लिए इस देखें:। (libiberty पुस्तकालय कि argv शैली वैक्टर manipulates के लिए प्रयोग किया जाता है का हिस्सा)

http://www.opensource.apple.com/source/gcc/gcc-5666.3/libiberty/argv.c

यह लाइसेंस प्राप्त जीएनयू एलजीपीएल है।

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