एक नल-पॉइंटर अपवाद को फेंक दें [बंद]


14

आपका कार्य एक शून्य-सूचक अपवाद उत्पन्न करना है। यही है, आपके कार्यक्रम को एक मूल्य को स्वीकार करना चाहिए जो इसे गैर-शून्य होने की उम्मीद करता है, और एक अपवाद / त्रुटि या दुर्घटना को फेंक देता है क्योंकि मूल्य शून्य है।

इसके अलावा, यह कोड पढ़ने से स्पष्ट नहीं हो सकता है कि मूल्य शून्य है। आपका लक्ष्य पाठक को यह स्पष्ट करना है कि मूल्य शून्य नहीं है, भले ही यह वास्तव में हो।

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

यह एक लोकप्रियता प्रतियोगिता है, इसलिए चतुर बनो!


क्या आप दिखा सकते हैं कि आपका क्या मतलब है?
य्प्निपन

इसे देखने के बाद, आप जो खोज रहे हैं, उससे कहीं अधिक एक कास्ट एरर है।
.वस

क्या मुझे संकलक बग का उपयोग करने की अनुमति है?
मार्क

1
@ मर्क यह एक लोकप्रियता प्रतियोगिता है; समुदाय को निर्णय लेने दें। मैं निश्चित रूप से एक कंपाइलर बग के लिए वोट करूंगा।
11684

जवाबों:


33

जावा

आइए किसी संख्या के निरपेक्ष मान की गणना करें। इस उद्देश्य के लिए जावा के पास Math.abs है, हालांकि हम जिस संख्या का उपयोग कर रहे हैं वह कभी-कभी शून्य हो सकती है। तो हमें उस मामले से निपटने के लिए एक सहायक विधि की आवश्यकता है:

public class NPE {
    public static Integer abs(final Integer x) {
        return x == null ? x : Math.abs(x);
    }

    public static void main(final String... args) {
        System.out.println(abs(null));
    }
}

यदि x शून्य है, तो null लौटें, अन्यथा Math.abs () का उपयोग करें।
कोड बहुत सरल और स्पष्ट है, और ठीक काम करना चाहिए ... है ना?

वैसे, इस लाइन का उपयोग करने के बजाय:

return x == null ? null : Math.abs(x);

सही ढंग से काम करता है। मैंने इसे बिगाड़ने वाला बनाने के बारे में सोचा, लेकिन .. मुझे लगता है कि यह बहुत ही हैरान करने वाला है :)

ठीक है, एक स्पष्टीकरण:

सबसे पहले, Math.abs एक पूर्णांक नहीं लेता है, लेकिन एक इंट (अन्य संख्यात्मक प्रकारों के लिए अतिभारित तरीके भी हैं) और एक इंट भी देता है। जावा में, int एक आदिम प्रकार है (और अशक्त नहीं हो सकता है) और Integer इसकी संबंधित कक्षा है (और अशक्त हो सकती है)। जावा संस्करण 5 के बाद से, इंट और इंटेगर के बीच रूपांतरण स्वचालित रूप से आवश्यक होने पर किया जाता है। तो Math.abs x ले सकता है, स्वचालित रूप से int में परिवर्तित हो जाता है, और एक int वापस कर देता है।

अब अजीब हिस्सा है: जब टर्नरी ऑपरेटर (:) को 2 भावों से निपटना पड़ता है, जहां एक में एक आदिम प्रकार होता है और दूसरे में इसका एक ही वर्ग होता है (जैसे इंट और इंटेगर), तो एक को उम्मीद होगी कि जावा आदिम में बदल जाएगा वर्ग के लिए (उर्फ "मुक्केबाजी"), विशेष रूप से जब प्रकार की आवश्यकता होती है (यहां विधि से लौटने के लिए) संदर्भ (वर्ग) प्रकार है, और पहली अभिव्यक्ति भी संदर्भ प्रकार की है। लेकिन जावा बिल्कुल विपरीत करता है: यह संदर्भ प्रकार को आदिम प्रकार (उर्फ "अनबॉक्सिंग") में परिवर्तित करता है। तो हमारे मामले में, यह x को int में बदलने की कोशिश करेगा, लेकिन int शून्य नहीं हो सकता है, इस प्रकार यह एक NPE फेंकता है।

यदि आप ग्रहण का उपयोग करके इस कोड को संकलित करते हैं, तो आपको वास्तव में एक चेतावनी मिलेगी: "अशक्त सूचक अभिगम: प्रकार की यह अभिव्यक्ति पूर्णांक अशक्त है, लेकिन इसके लिए ऑटो-अनबॉक्सिंग की आवश्यकता है"


/programming/7811608/java-npe-in-ternary-operator-with-autoboxing
/programming/12763983/nullpointerexception-through-auto-boxing-behavior-of-java -ternary-ऑपरेटर



SPOILERS क्या होता है जब x = null? (मुझे पहले ही पता चल गया।)
११६ fig४

@ 11684 जब x शून्य नहीं है, तो यह ठीक काम करता है
aditsu छोड़ दिया क्योंकि SE EVIL

तब मुझे लगता है कि मुझे नहीं पता कि यह कैसे काम करता है। यदि यह काम करता है जब x शून्य नहीं है और मैं इस बारे में सही हूं कि यह क्यों फेंकता है, तो बृहदान्त्र को दो इंद्रियों में पार्स किया जाना चाहिए (जो मैं एक भाषा विनिर्देश में नहीं डालूंगा)।
11684

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

23

सी

प्रत्येक सी प्रोग्रामर ने यह त्रुटि की, कम से कम एक बार।

#include <stdio.h>

int main(void) {
    int n=0;
    printf("Type a number : ");
    scanf("%d",n);
    printf("Next number is : %d",n+1);
    return 0;
}

कारण :

scanfएक संकेतक लेता है ( int *) तर्क में, यहाँ 0पारित किया गया है (NULL-पॉइंटर)

ठीक कर:

scanf("%d",&n);

http://ideone.com/MbQhMM


1
ऐसा बिलकुल नहीं है। scanfएक वैरेडिक फ़ंक्शन है, और गलत प्रकार का तर्क ( int) दिया गया था, जब यह अपेक्षित था int *। क्योंकि C (मुझे पता है, कंपाइलर इसका पता लगा सकते हैं scanf) वैरिएबल फ़ंक्शन में प्रकारों की जांच नहीं कर सकते हैं, यह खुशी से संकलित करता है। 0वास्तव में अशक्त सूचक शाब्दिक है, लेकिन यह केवल सीधे उपयोग किए गए शाब्दिक पर ही लागू होता है, बिना किसी चर में संग्रहीत किए। nकभी भी एक शून्य सूचक नहीं था।
कोनराड बोरोस्की

इस फ़ंक्शन को ठीक करने के लिए आपको स्कैनफ के रिटर्न मान की भी जांच करनी होगी।
डेविड ग्रेसन

1
@ डेविड यह रिटर्न वैल्यू की जाँच के बिना सही नहीं है, लेकिन यह क्रैश नहीं होगा या यूबी - एन को
इनवाइट नहीं

14

पीएचपी

इसने मुझे कई बार काटा है।

<?php

class Foo {
  private $bar;

  function init() {
    $this->bar = new Bar();
  }

  function foo() {
    $this->bar->display_greeting(); // Line 11
  }
}

class Bar {
  function display_greeting() {
    echo "Hello, World!";
  }
}

$foo_instance = new Foo();
$foo_instance->init();
$foo_instance->foo();

अपेक्षित परिणाम:

Hello, World!

वास्तविक परिणाम:

Fatal error: Call to a member function display_greeting() on a non-object on line 11

उर्फ नलपॉइंटेरैसेप्शन

कारण:

डिफ़ॉल्ट रूप से, कंस्ट्रक्टर सिंटैक्स PHP 4.x के साथ पीछे की ओर संगत है, और इस तरह, फ़ंक्शन fooक्लास के लिए एक वैध कंस्ट्रक्टर है Foo, और इस प्रकार डिफ़ॉल्ट खाली कंस्ट्रक्टर को ओवरराइड करता है। अपनी परियोजना में एक नाम स्थान जोड़कर इस तरह की त्रुटि से बचा जा सकता है।


9

कॉफीस्क्रिप्ट (Node.js पर)

CoffeeScript में, ?अस्तित्वगत ऑपरेटर है। यदि चर मौजूद है, तो इसका उपयोग किया जाता है, अन्यथा दाहिने हाथ की ओर का उपयोग किया जा रहा है। हम सभी जानते हैं कि पोर्टेबल प्रोग्राम लिखना कठिन है। बिंदु में मामला, जावास्क्रिप्ट में मुद्रण निर्दिष्ट है। ब्राउज़रों का उपयोग alert(या document.write), स्पाइडरमंकी शेल उपयोग करता है print, और Node.js उपयोग करता है console.log। यह पागल है, लेकिन कॉफीस्क्रिप्ट इस मुद्दे के साथ मदद करता है।

# Portable printer of "Hello, world!" for CoffeeScript

printingFunction = alert ? print ? console.log
printingFunction "Hello, world!"

चलो इसे Node.js. के तहत चलाते हैं आखिरकार, हम यह सुनिश्चित करना चाहते हैं कि हमारी स्क्रिप्ट काम करती है।

ReferenceError: print is not defined
  at Object.<anonymous> (printer.coffee:3:1)
  at Object.<anonymous> (printer.coffee:3:1)
  at Module._compile (module.js:456:26)

उह, आप उस बारे में शिकायत क्यों करेंगे, जब alertयह भी परिभाषित नहीं है?

किसी कारण से, CoffeeScript में, ?बाएं सहयोगी है, जिसका अर्थ है कि यह केवल बाईं ओर के लिए अपरिभाषित चर को अनदेखा करता है। यह अपरिचित है, क्योंकि जाहिर है कुछ डेवलपर्स पर निर्भर हो सकता है? साहचर्य छोड़ा जा रहा है


8

माणिक

एक यूनिक्स क्लोन के पथ में जागो।

p = ENV['PATH'].split ':'

# Find an executable in PATH.
def find_exec(name)
  p.find {|d| File.executable? File.join(d, name)}
end

printf "%s is %s\n", 'awk', find_exec('awk')

ऊप्स!

$ ruby21 find-awk.rb
find-awk.rb:5:in `find_exec': undefined method `find' for nil:NilClass (NoMethodError)
        from find-awk.rb:8:in `<main>'

त्रुटि से, हम जानते हैं कि p.findकहा जाता है nil.find, इसलिए pहोना चाहिए nil। ये कैसे हुआ?

रूबी में, defस्थानीय चर के लिए अपना दायरा है, और बाहरी दायरे से स्थानीय चर कभी नहीं लेता है। इस प्रकार असाइनमेंट p = ENV['PATH'].split ':'कार्यक्षेत्र में नहीं है।

एक अपरिभाषित चर आमतौर पर कारण बनता है NameError, लेकिन pएक विशेष मामला है। रूबी नाम की एक वैश्विक पद्धति है p। तो p.find { ... }एक विधि कॉल हो जाता है, जैसे p().find { ... }। जब pकोई तर्क नहीं होता है, तो यह वापस आ जाता है nil। (कोड गोल्फर के लिए pएक शॉर्टकट के रूप में उपयोग करते हैं nil।) फिर nil.find { ... }उठाता है NoMethodError

मैं इसे पायथन में कार्यक्रम को फिर से लिखकर ठीक करता हूं।

import os
import os.path

p = os.environ['PATH'].split(':')

def find_exec(name):
    """Find an executable in PATH."""
    for d in p:
        if os.access(os.path.join(d, name), os.X_OK,
                     effective_ids=True):
            return d
    return None

print("%s is %s" % ('awk', find_exec('awk')))

यह काम करता हैं!

$ python3.3 find-awk.py 
awk is /usr/bin

मैं शायद इसे प्रिंट करना चाहता हूं awk is /usr/bin/awk, लेकिन यह एक अलग बग है।


7

सी#

With()stringवस्तु के लिए एक विस्तार विधि है , जो अनिवार्य रूप से सिर्फ एक उपनाम है string.Format()

using System;

namespace CodeGolf
{
    internal static class Program
    {
        private static void Main()
        {
            Console.WriteLine( "Hello, {0}!".With( "World" ) );
        }

        private static string With( this string format, params object[] args )
        {
            Type str = Type.GetType( "System.string" );
            MethodInfo fmt = str.GetMethod( "Format", new[] { typeof( string ), typeof( object[] ) } );

            return fmt.Invoke( null, new object[] { format, args } ) as string;
        }
    }
}

अच्छा लग रहा है, है ना? गलत।

Type.GetType()एक पूरी तरह से योग्य, केस-संवेदी प्रकार के नाम की आवश्यकता है। समस्या यह है कि System.stringअस्तित्व में नहीं है; वास्तविक प्रकार के stringलिए सिर्फ एक उपनाम है :। ऐसा लगता है कि यह काम करना चाहिए, लेकिन अपवाद को फेंक देगा क्योंकि ।System.Stringstr.GetMethod()str == null

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


यह एक बहुत अच्छा है: D
Knerd

यह थोड़ा बहुत स्पष्ट है। क्योंकि वहाँ एक ही बात करने के लिए दो तरीके हैं पाठक एक तत्काल सुराग मिल .GetType()और typeof()और इस तरह एक गलती के लिए अग्रणी जब परिणाम समान नहीं है। मुझे लगता है कि पोस्टर बुलेट प्रूफ लुकिंग कोड चाहता था, जो नहीं है।
72२

इस विस्तार विधि में प्रतिबिंब का उपयोग क्यों किया जाएगा? स्पष्ट कोड है return string.Format(format, args);। यदि प्रतिबिंब (दूसरे उपयोग के मामले में) की आवश्यकता होती है, तो कोई उपयोग करेगा typeof(string)(संकलन-समय पर आवरण गलतियों को पकड़ता है, कोई जादुई स्ट्रिंग नहीं), न कि स्थैतिक GetTypeविधि। तो उदाहरण "अवास्तविक" लगता है।
जेपी स्टिग नील्सन

4

Unity3D

public GameObject asset;

तब आप वहां की संपत्ति को खींचने और छोड़ने के लिए भूल जाते हैं और बूम, एकता में विस्फोट होता है। हमेशा होता है।


3
रुको, एकता 3 डी में विकास के लिए एक माउस की आवश्यकता है?
आइनेकियो

1
@Einacio अगर आप चीजों को आसान बनाना चाहते हैं तो आप किसी एसेट को एक वैरिएबल में ड्रैग कर सकते हैं। बेहद सुविधाजनक। लेकिन अगर आप चाहें तो आप इसके बिना भी कोड कर सकते हैं।
फैब्रियो

4

माणिक

एक सरणी के उत्पाद को लेने के लिए बस कुछ सरल कोड।

number_array = [2,3,9,17,8,11,14]
product = 1
for i in 0..number_array.length do
  product *= number_array[i]
end
puts product

दो बातें यहाँ। एक यह है कि ..रेंज ऑपरेटर समावेशी है । तो 0..xहै x + 1 तत्वों और एक्स शामिल हैं। इसका मतलब है कि हम सरणी की सीमा से अधिक है। दूसरी बात यह है कि जब आप रूबी में ऐसा करते हैं, तो यह आपको nilबैक देती है। यह बहुत मजेदार है जब, कहते हैं, आपका कार्यक्रम बग के बादexcept दस पंक्तियों को फेंकता है ।


यह भी स्पष्ट है। यह for (int i = 0; i <= arr.length; i++)जावा में करने जैसा है ।
कोल जॉनसन

3

एंड्रॉयड

मैं देख रहा हूं कि ऐसा अक्सर होता है। एक व्यक्ति अगली गतिविधि (शायद एक स्थिति कोड, मानचित्र डेटा, जो भी हो) के लिए एक संदेश देता है, और इसमें से एक अशक्त खींचता है Intent

पहली नज़र में यह बहुत उचित लगता है। बस:

  • सुनिश्चित करें कि संदेश शून्य नहीं है
  • इसे इरादे में पैक करें
  • नई गतिविधि शुरू करें
  • नई गतिविधि में इरादा रखें
  • टैग द्वारा संदेश निकालें

में MenuActivity.java:

private void startNextActivity(String message){
    // don't pass a null!
    if(message == null)                        
        message = "not null";        

    // put message in bundle with tag "message"
    Bundle msgBundle = new Bundle();
    msgBundle.putString("message", message);   

    // pack it into a new intent
    Intent intent = new Intent(this, NextActivity.class);
    intent.putExtras(msgBundle);               
    startActivity(intent);
}

में NextActivity.java:

private void handleMessage(){
    // get Intent
    Intent received = getIntent();
    if(received == null){
        Log.d("myAppTag","no intent? how does this even happen?");
        finish();
    }
    // get String with tag "message" we added in other activity
    String message = received.getStringExtra("message");
    if(message.length() > 10){
        Log.d("myAppTag", "my message is too long! abort!");
        finish();
    }
    // handle message here, etc
    // ...
    // too bad we never GET here!
}

FWIW, जावाडोक करता है का कहना है कि Intent.getStringExtra(String)वापस आ सकते हैं null, लेकिन केवल तभी टैग नहीं मिला था। स्पष्ट रूप से मैं एक ही टैग का उपयोग कर रहा हूं, इसलिए यह कुछ और होना चाहिए ...


2
इस उत्तर के साथ समस्या यह है कि लोग Android के विकास से परिचित नहीं हैं (जैसे कि मेरे) इसकी सराहना नहीं कर पाएंगे।
जॉन ड्वोरक

@JanDvorak सहमत हैं, लेकिन कोई बड़ी बात नहीं है। साइट पर ऐसे अन्य उत्तर हैं जिनकी मैं पूरी तरह से सराहना नहीं करता हूं। :)
ज्योबिट्स

3

सी

बफर से बस एक त्वरित पढ़ा, जहां संभावित खतरे को दस्तावेज करने के लिए प्रोग्रामर भी काफी दयालु रहा है!

char* buffer;
int main( void )
{
    ///!!WARNING: User name MUST NOT exceed 1024 characters!!\\\
    buffer = (char*) malloc( 1024 );
    printf("Please Input Your Name:");
    scanf("%s", buffer);
}

यदि आप दुर्भावनापूर्ण कोड की अपेक्षा कर रहे हैं तो बहुत ही सरल और स्पष्ट ट्रिक। '\' समाप्त होने वाली टिप्पणी नई पंक्ति से बच जाती है, इसलिए बफर को कभी भी मेमोरी आवंटित नहीं की जाती है। यह तब स्कैनफेल में विफल हो जाएगा, क्योंकि बफर NULL होगा (चूंकि फ़ाइल स्कोप वैरिएबल C में आरंभिक रूप से शून्य हैं)।


0

निमरॉड

type TProc = proc (a, b: int): int

proc func1(a, b: int): int=a+b
proc func2(a, b: int): int=a-b

proc make_func(arg: int, target: var TProc)=
  if arg == 1:
    target = func1
  elif arg == 2:
    target = func2
  else:
    raise newException(EIO, "abc")

var f, f2: TProc

try:
  make_func(2, f)
  make_func(3, f2)
except EIO:
  discard

echo f(1, 2)
echo f2(3, 4)

यहां जो हो रहा है वह थोड़ा जटिल है। निम्रोद में, प्रक्रियाएं डिफ़ॉल्ट रूप से आरंभिक होती हैं nil। पहली make_funcकॉल में, यह सफल होता है। दूसरा, हालांकि, एक अपवाद फेंकता है और f2असिंचित छोड़ देता है । इसे तब त्रुटि कहा जाता है।


0

सी#

यह शास्त्रीय है। बहुत उपयोगी विधि FindStringRepresentationOf, निर्दिष्ट प्रकार पैरामीटर का एक नया उदाहरण बनाने तो उस उदाहरण का स्ट्रिंग प्रतिनिधित्व मिल जाएगा।

निश्चित रूप से nullएक नया उदाहरण बनाने के तुरंत बाद जांच करना बेकार होगा , इसलिए मैंने ऐसा नहीं किया है ...

static void Main()
{
  FindStringRepresentationOf<DateTime>();  // OK, "01/01/0001 00:00:00" or similar
  FindStringRepresentationOf<DateTime?>(); // Bang!
}

static string FindStringRepresentationOf<TNewable>() where TNewable : new()
{
  object goodInstance = new TNewable();
  return goodInstance.ToString();
}

बदलने objectमें स्थानीय चर घोषणा में TNewable या में var(सी # 3 और बाद में) बनाता है समस्या का समाधान। संकेत: .NET फ्रेमवर्क में Nullable<T>(aka T?) का बॉक्सिंग एक विसंगति है।

ऊपर दिए गए अदृश्य पाठ में वर्णित समस्या को ठीक करने के बाद, कोशिश करें goodInstance.GetType()(अंतर GetType(), जो कि इसके विपरीत है ToString(), गैर-आभासी है, इसलिए वे overrideइसे टाइप में नहीं कर सकते हैं Nullable<>)।


0

सी ++:

#include <iostream>
#include <cstring>
#include <vector>
#include <conio.h>
#include <string>

using namespace std;

class A
{
public:
    string string1;
    A()
    {
        string1 = "Hello World!";
    }
};
A *a_ptr;

void init()
{
    A a1;
    a_ptr = &a1;
}

int main()
{
    init();
    cout<<a_ptr->string1;
    _getch();
    return 0;
}

आप क्या उम्मीद करेंगे "हैलो वर्ल्ड!" मुद्रित होना। लेकिन आपको स्क्रीन पर केवल कचरा दिखाई देगा।

यहां a1 तबाह हो जाता है जब स्कोप इनिट () समाप्त हो जाता है। तो a_ptr, जैसा कि यह a1 को इंगित करता है, कचरा पैदा करेगा।


0

सी

#define ONE 0 + 1

int main(void) {
    printf("1 / 1 = %d\n", 1 / ONE);
    return 0;
}

व्याख्या

प्रीप्रोसेसर वास्तव में गणना नहीं करता है 0 + 1, इसलिए ONEशाब्दिक रूप से परिभाषित किया गया है 0 + 1, जिसके परिणामस्वरूप 1 / 0 + 1, जो शून्य से एक विभाजन है, और एक अस्थायी बिंदु अपवाद में परिणाम है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.