2010-06-04 27 views
9

मैं यूनिक्स में सी में प्रोग्रामिंग कर रहा हूं, और मैं कीबोर्ड से इनपुट पढ़ने के लिए gets का उपयोग कर रहा हूं।क्यों() काम नहीं कर रहा है?

warning: this program uses gets(), which is unsafe. 

किसी को भी मेरे कारण है कि यह हो रहा है बता सकते हैं: मैं हमेशा इस चेतावनी और कार्यक्रम चलना बंद हो जाते हैं?

+0

यह एक असुरक्षित कार्य है; बफर ओवरफ्लो हमलों को जारी किया जा सकता है यदि कार्यक्रम ऐसे कार्यों का उपयोग करते हैं जो बफर आकार – INS

+0

की जांच करने की संभावना प्रदान नहीं करते हैं, तो अगर मैं काम करता है() के बजाय scanf() का उपयोग करता हूं, लेकिन मुझे कीबोर्ड और प्रोग्राम से 2 इनपुट पढ़ना होगा मैंने पहली बार पढ़ा है के बाद बंद हो जाता है। क्यूं कर? यह कोड है: चार उपयोगकर्ता; चार पास; printf ("Iser ID"); स्कैनफ़ ("% s", उपयोगकर्ता); printf ("पिन कोड:"); स्कैनफ ("% s", पास); – Peiska

+1

@peiska: कार्यक्रम पहले के बाद बंद हो जाता है क्योंकि यह आपके लिए दूसरा स्थान दर्ज करने का इंतजार कर रहा है। आप स्वयं उस दूसरे 'स्कैनएफ' को वहां डाल देते हैं। यह आपको आश्चर्य क्यों करता है कि कार्यक्रम "बंद हो जाता है"? – AnT

उत्तर

8

जैसा कि पिछले उत्तरों में उल्लेख किया गया है के बजाय fgets का उपयोग करें।

लेकिन यह gets जैसा नहीं है, यह बिल्कुल काम नहीं करता है, यह बहुत ही असुरक्षित है। मेरा अनुमान है कि आपके पास आपके कोड में एक बग है जो fgets के साथ दिखाई देगा, इसलिए कृपया अपना स्रोत पोस्ट करें।

EDIT आपकी टिप्पणी में दी गई अद्यतन जानकारी के आधार पर मेरे पास कुछ सुझाव हैं।

  • मैं आपकी मूल भाषा में एक अच्छा सी ट्यूटोरियल खोजने की सलाह देता हूं, Google आपका मित्र है। एक पुस्तक के रूप में मैं The C Programming Language

  • यदि आपके पास नई जानकारी है तो उन्हें अपने मूल पोस्ट में संपादित करना एक अच्छा विचार है, खासकर यदि यह कोड है, तो यह लोगों के लिए समझने में आसान होगा कि आपका क्या मतलब है।

  • आप एक स्ट्रिंग को मूल रूप से वर्णों की एक सरणी पढ़ने की कोशिश कर रहे हैं, जो कि एक ही चरित्र में है, जो निश्चित रूप से विफल हो जाएगा। आप जो करना चाहते हैं वह निम्न जैसा है।

    char username[256]; 
    char password[256]; 
    scanf("%s%s", username, password); 
    

    टिप्पणी करने के लिए/संपादन स्वतंत्र महसूस, मैं बुनियादी सी में भी बहुत जंग लगी हूँ

संपादित 2 jamesdlin के रूप में चेतावनी दी थी, scanf के उपयोग gets के रूप में के रूप में खतरनाक है।

+0

आपका 'स्कैनफ़' उपयोग' हो जाता है 'जितना खराब है। ('स्कैनफ़'' का उपयोग करने से बचें: http://c-faq.com/stdio/scanfprobs.html) – jamesdlin

+0

@jamesdlin सिर के लिए धन्यवाद, मुझे बफर ओवरफ्लो समस्या के बारे में पता नहीं था, हालांकि मैंने भाग लिया है पहले स्कैनफ के साथ अन्य समस्याएं। – ponzao

13

gets असुरक्षित है क्योंकि आप इसे एक बफर देते हैं, लेकिन आप यह नहीं बताते कि बफर कितना बड़ा है। इनपुट बफर के अंत से पहले लिख सकता है, जो आपके कार्यक्रम को काफी शानदार तरीके से उड़ा सकता है। fgets उपयोग करने के बजाय एक सा बेहतर है क्योंकि आप यह कहना कितना बड़ा बफर है इस तरह, यह है:

const int bufsize = 4096; /* Or a #define or whatever */ 
char buffer[bufsize]; 

fgets(buffer, bufsize, stdin); 

... इसलिए प्रदान की आप इसे सही जानकारी देते हैं, यह बफर के अंत अतीत बारे में नहीं है और चीजों को उड़ाना।

थोड़ा OT, लेकिन:

आप बफर आकार के लिए एक const int उपयोग करने के लिए नहीं है, लेकिन मैं करूंगा दृढ़ता से सुझाव है कि आप सिर्फ दोनों स्थानों में एक शाब्दिक संख्या डाल नहीं है, क्योंकि अनिवार्य रूप से आप एक बदल जाएगा लेकिन बाद में नहीं। कंपाइलर मदद कर सकता है:

char buffer[4096]; 
fgets(buffer, (sizeof buffer/sizeof buffer[0]), stdin); 

वह अभिव्यक्ति संकलित समय पर संकलित हो जाती है, रनटाइम नहीं। यह टाइप करने के लिए एक दर्द है, तो मैं हेडर की मेरी हमेशा की तरह सेट में मैक्रो का उपयोग करने के लिए इस्तेमाल:

#define ARRAYCOUNT(a) (sizeof a/sizeof a[0]) 

... लेकिन मैं अपने शुद्ध सी के साथ पुराने हो चुके कुछ साल कर रहा हूँ, वहाँ शायद एक बेहतर तरीका है इन दिनों।

+0

यदि आप 'char' की सरणी से निपट रहे हैं, तो परिभाषा के अनुसार 'sizeof buffer [0]' 'sizeof (char) == 1' के रूप में विभाजित करने की आवश्यकता नहीं है, यानी फ़ंक्शन कॉल को' fgets ' (बफर, आकार बफर, stdin) ' – Christoph

+0

@ क्रिस्टोफ: क्या आप * निश्चित * हैं कि 'char' सभी प्लेटफार्मों पर एक बाइट होगा, और/या यदि यह दो बाइट्स (कहना) है, तो बफ आकार तर्क' fgets * बाइट्स * के बजाए * वर्ण * के रूप में लागू किया जाएगा? मैंने देखा है कि अधिकांश दस्तावेज़ बाइट्स कहा है। मैं थोड़ी देर में सी खेल रहा हूं और मुझे पता है कि यह सामान अधिक जटिल हो गया है, इसलिए मैं कोड में थोड़ा रक्षात्मक था। लेकिन हाँ, @ ओपी, * अगर * उन धारणाएं सुरक्षित हैं, तो आप 'char' सरणी के साथ गणना छोड़ सकते हैं (लेकिन' id', 'long', आदि के साथ इस मुहावरे के समान अनुप्रयोग नहीं)। –

+0

@ टीजे। पाउडर: सी मानक * परिभाषित करता है * 'char' 1 बाइट होना चाहिए। – jamesdlin

5

man gets का कहना है:

कभी का उपयोग हो जाता है()। क्योंकि यह असंभव अग्रिम कितने वर्ण हो जाता है() पढ़ा जाएगा में डेटा जानने के बिना बताने के लिए है, और क्योंकि हो जाता है() बफर के अंत अतीत पात्रों स्टोर करने के लिए जारी रहेगा, यह बहुत उपयोग करने के लिए खतरनाक है । यह का उपयोग कंप्यूटर सुरक्षा को तोड़ने के लिए किया गया है। इसके बजाए fgets() का प्रयोग करें।

1

gets() असुरक्षित है। यह एक पैरामीटर लेता है, एक चार बफर के लिए एक सूचक। खुद से पूछें कि आपको उस बफर को कितना बड़ा बनाना है और उपयोगकर्ता कितनी देर तक वापसी कुंजी को मारने के बिना इनपुट टाइप कर सकता है।

असल में, बफर ओवरफ्लो को() - fgets() का उपयोग करने से रोकने का कोई तरीका नहीं है।

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