एक ही वेक्टर के दो संदर्भ वेक्टर के प्रत्येक तत्व के लिए अलग-अलग मेमोरी एड्रेस क्यों लौटाते हैं?


9

मैं आर सीख रहा हूं और वर्तमान में मैं इस पुस्तक को पढ़ रहा हूं । यह सुनिश्चित करने के लिए कि मैं अवधारणा को समझता हूं, मैंने निम्नलिखित परीक्षण चलाया जो मेरे लिए काफी भ्रमित करने वाला था और यदि आप इसे स्पष्ट कर सकते हैं तो मैं सराहना करूंगा। यहाँ परीक्षण है, जिसे मैं सीधे टर्मिनल से आर शेल में चलाता था (RStudio या Emacs ESS का उपयोग नहीं करता)।

> library(lobstr)
>
> x <- c(1500,2400,8800)
> y <- x
> ### So the following two lines must return the same memory address
> obj_addr(x)
[1] "0xb23bc50"
> obj_addr(y)
[1] "0xb23bc50"
> ### So as I expected, indeed both x and y point to the same memory 
> ### location: 0xb23bc50
>
>
>
> ### Now let's check that each element can be referenced by the same
> ### memory address either by using x or y
> x[1]
[1] 1500
> y[1]
[1] 1500
> obj_addr(x[1])
[1] "0xc194858"
> obj_addr(y[1])
[1] "0xc17db88"
> ### And here is exactly what I don't understand: x and y point 
> ### to the same memory address, so the same must be true for 
> ### x[1] and y[1]. So how come I obtain two different memory
> ### addresses for the same element of the same vector?
>
>
>
> x[2]
[1] 2400
> y[2]
[1] 2400
> obj_addr(x[2])
[1] "0xc15eca0"
> obj_addr(y[2])
[1] "0xc145d30"
> ### Same problem!
>
>
>
> x[3]
[1] 8800
> y[3]
[1] 8800
> obj_addr(x[3])
[1] "0xc10e9b0"
> obj_addr(y[3])
[1] "0xc0f78e8"
> ### Again the same problem: different memory addresses

क्या आप मुझे बता सकते हैं कि मेरी गलती कहां है और इस समस्या में मुझे क्या गलत लगा है?


1
मैं R नहीं जानता, लेकिन अन्य भाषाओं में आपके पास मूल्य और संदर्भ प्रकार हैं। यदि पूर्णांक C ++ या C # में मान प्रकार है, तो कोई भी असाइनमेंट नया पूर्णांक बनाएगा। इसलिए प्रत्येक पूर्णांक का अपना पता होगा।
छात्रावास

1
वास्तव में, obj_addr(x[1])दो बार चलने पर भी आपको अलग-अलग परिणाम देने चाहिए, क्योंकि हर नए पूर्णांक का अपना पता होगा।
बास

@Bas मैंने परीक्षण किया कि आपने क्या उल्लेख किया है, जो क्रमिक रूप से obj_addr (x [1]) चला रहा है, और वास्तव में ऐसा करने पर, R हर बार एक अलग परिणाम (अलग मेमोरी एड्रेस) देता है। लेकिन मुझे समझ में नहीं आता है, क्योंकि जैसा कि मुझे लगता है कि मैं कुछ भी असाइन नहीं करता हूं, इसलिए मैं एक नई वस्तु नहीं बनाता (जिसके लिए स्पष्ट रूप से एक नया पता होगा क्योंकि ऑब्जेक्ट आर में अपरिवर्तनीय हैं)। मेरे लिए obj_addr (x [1]) का अर्थ है कि मैं अभी पहले से मौजूद वस्तु को पढ़ रहा हूं।
user17911

जवाबों:


5

कोई भी आर ऑब्जेक्ट एक सी (पॉइंटर -डाल्ड SEXP- ए) "मल्टी-ऑब्जेक्ट" ( struct) है। इसमें lengthR ऑब्जेक्ट के बारे में जानकारी (जिसे R को संचालित करने की आवश्यकता है, उदाहरण के लिए , किसी ऑब्जेक्ट को कॉपी करने के लिए-और भी बहुत कुछ पता है) और आर ऑब्जेक्ट के वास्तविक डेटा के बारे में भी, जिसे हम एक्सेस करते हैं।

lobstr::obj_addr, संभवत:, एक SEXPअंक के लिए स्मृति पता देता है। मेमोरी के उस हिस्से में R ऑब्जेक्ट के बारे में जानकारी और डेटा दोनों होते हैं । R वातावरण के भीतर से हम प्रत्येक R ऑब्जेक्ट में वास्तविक डेटा की (पॉइंटर) एक्सेस करने की आवश्यकता नहीं कर सकते हैं।

जैसा कि एडम अपने जवाब में कहते हैं, फ़ंक्शन C ऑब्जेक्ट में मौजूद डेटा के nth तत्व को एक नई C ऑब्जेक्ट में [ कॉपी करता है और अपने SEXPपॉइंटर को R पर लौटाता है। हर बार [कॉल करने के बाद, एक नई C ऑब्जेक्ट बनाई जाती है और R पर वापस आ जाती है।

हम R के माध्यम से अपनी वस्तु के वास्तविक डेटा के प्रत्येक तत्व के मेमोरी एड्रेस तक नहीं पहुंच सकते हैं। लेकिन चारों ओर थोड़ा सा खेलते हुए, हम सी एपीआई का उपयोग करके संबंधित पते का पता लगा सकते हैं:

पतों को पाने के लिए एक समारोह:

ff = inline::cfunction(sig = c(x = "integer"), body = '
             Rprintf("SEXP @ %p\\n", x);

             Rprintf("first element of SEXP actual data @ %p\\n", INTEGER(x));

             for(int i = 0; i < LENGTH(x); i++) 
                 Rprintf("<%d> @ %p\\n", INTEGER(x)[i], INTEGER(x) + i);

             return(R_NilValue);
     ')

और हमारे डेटा के लिए आवेदन:

x = c(1500L, 2400L, 8800L)  #converted to "integer" for convenience
y = x

lobstr::obj_addr(x)
#[1] "0x1d1c0598"
lobstr::obj_addr(y)
#[1] "0x1d1c0598"

ff(x)
#SEXP @ 0x1d1c0598
#first element of SEXP actual data @ 0x1d1c05c8
#<1500> @ 0x1d1c05c8
#<2400> @ 0x1d1c05cc
#<8800> @ 0x1d1c05d0
#NULL
ff(y)
#SEXP @ 0x1d1c0598
#first element of SEXP actual data @ 0x1d1c05c8
#<1500> @ 0x1d1c05c8
#<2400> @ 0x1d1c05cc
#<8800> @ 0x1d1c05d0
#NULL

हमारी वस्तु के डेटा तत्वों के बीच क्रमिक मेमोरी का अंतर intप्रकार के आकार के बराबर होता है :

diff(c(strtoi("0x1d1c05c8", 16), 
       strtoi("0x1d1c05cc", 16), 
       strtoi("0x1d1c05d0", 16)))
#[1] 4 4

[फ़ंक्शन का उपयोग करना :

ff(x[1])
#SEXP @ 0x22998358
#first element of SEXP actual data @ 0x22998388
#<1500> @ 0x22998388
#NULL
ff(x[1])
#SEXP @ 0x22998438
#first element of SEXP actual data @ 0x22998468
#<1500> @ 0x22998468
#NULL

यह व्यापक उत्तर की आवश्यकता से अधिक हो सकता है और वास्तविक तकनीकी पर सरल है, लेकिन, उम्मीद है, एक स्पष्ट "बड़ी" तस्वीर प्रदान करता है।


बहुत बढ़िया! मैं वास्तव में आर जैसे पूरी तरह से शुरुआती लोगों के लिए इस तरह के विस्तृत और स्पष्ट स्पष्टीकरण के लिए आपको बहुत धन्यवाद देता हूं। इसके अलावा, आर का लचीलापन और अन्य प्रोग्रामिंग भाषाओं के साथ इसके संभावित शक्तिशाली इंटरैक्शन को दिखाने में आपका उदाहरण बहुत प्रभावशाली है। आपके समय और आपकी मदद के लिए बहुत धन्यवाद।
user17911

3

यह देखने का एक तरीका है। मुझे यकीन है कि एक और तकनीकी दृष्टिकोण है। याद रखें कि आर में, लगभग सब कुछ एक फ़ंक्शन है। यह निकालने समारोह भी शामिल है, [। यहाँ एक समकक्ष कथन है x[1]:

> `[`(x, 1)
[1] 1500

तो आप जो कर रहे हैं वह एक फ़ंक्शन चला रहा है जो एक मान (चेक आउट ?Extract) लौटाता है । वह मान पूर्णांक है। जब आप दौड़ते हैं obj_addr(x[1]), तो यह फ़ंक्शन का मूल्यांकन करता है x[1]और फिर आपको obj_addr()उस फ़ंक्शन का रिटर्न देता है, न कि उस सरणी के पहले तत्व का पता जिसे आप दोनों के लिए बाध्य करते हैं xऔर y


आपकी मदद और मेरी समस्या पर ध्यान देने के लिए आपका बहुत-बहुत धन्यवाद। वास्तव में यह वही है जो मुझे नहीं पता था, अर्थात, "एक्सट्रैक्ट" द्वारा एक मूल्य को पुनः प्राप्त करना वास्तव में एक नई वस्तु बनाता है। जैसा कि मैंने कहा कि मैं वास्तव में आर में शुरुआत कर रहा हूं! आपके समय और आपके विवरण के लिए बहुत-बहुत धन्यवाद।
user17911
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.