2014-04-01 5 views
9

निम्नलिखित कोड reproducibly जब आर में मार डाला segfaults (3.0.2 लेकिन मैं इसे अन्य संस्करणों के लिए समान है यह सोचते हैं रहा हूँ):सेटिंग parent.env, `detach` द्वारा पीछा किया, segfaults

ns = new.env(parent = .BaseNamespaceEnv) 
local(f <- function() 42, envir = ns) 
x = list2env(as.list(ns), parent = as.environment(2)) 
parent.env(.GlobalEnv) = x 
detach() 

हाँ, मैं जानते हैं कि documentation on parent.env कहते

प्रतिस्थापन समारोह parent.env<- बेहद खतरनाक के रूप में यह तरीके कि आंतरिक सी कोड द्वारा बनाई गई मान्यताओं का उल्लंघन में विध्वंस परिवर्तन वातावरण के लिए इस्तेमाल किया जा सकता है। इसे निकट भविष्य में हटाया जा सकता है।

यही वह है जो मुझे यहां चल रहा है। हालांकि, मैं क्यों समझना चाहूंगा यह व्यवहार इस तरह से है, और इससे कैसे बचें।

निम्नलिखित सरल कोड करता इस समस्या नहीं है:

x = new.env(parent = as.environment(2)) 
local(f <- function() 42, envir = x) 
parent.env(.GlobalEnv) = x 
detach() 

... इसलिए ऐसा लगता है कि यह एक अंतर यह है कि x एक समारोह जिसका parent.env एक अलग (स्वाधीन) वातावरण होता है बनाता है।

इसी तरह, parent.env<- के बजाय attach का उपयोग करके कोई क्रैश नहीं होता है। (तो क्यों बस attach का उपयोग नहीं? क्योंकि मेरे कोड में, .GlobalEnv हिस्सा एक चर जो विभिन्न वातावरण का उल्लेख कर सकते है।)

क्रैश डम्प मुझसे कहता है कि segfault do_detach (envir.c) में होता है। शायद यह संबंधित है -

isSpecial = IS_USER_DATABASE(s); 
if(isSpecial) { 
    R_ObjectTable *tb = (R_ObjectTable*) R_ExternalPtrAddr(HASHTAB(s)); 
    if(tb->onDetach) tb->onDetach(tb); 
} 

मैं है पता नहीं क्या IS_USER_DATABASE करता है: कोड निम्नलिखित लाइनों में शामिल है? केवल मेरे पर्यावरण (.onDetach = function (x) x) में .onDetach विधि जोड़ने से मदद नहीं मिली।

+0

मुझे लगता है कि आपको आर-डेवेल पर पूछना होगा। Globalenv के माता-पिता के साथ चारों ओर गड़बड़ करना एक _really_ बुरा विचार की तरह लगता है। – hadley

उत्तर

0

पूर्णता 'के लिए, स्पष्ट वैकल्पिक हल के लिए कि क्या पर्यावरण .GlobalEnv है, और विशेष मामले के लिए परीक्षण करने के लिए है यह:

new_env = something # e.g. .GlobalEnv 

if (identical(new_env, .GlobalEnv)) 
    attach(x) 
else { 
    parent.env(x) = parent.env(new_env) 
    parent.env(new_env) = x 
} 

... लेकिन इस प्रारंभिक बग की व्याख्या नहीं करता है और, मैं डर, केवल इसे हटाने के बजाय समस्या को छुपाता है।

1

नोट: यह वास्तविक उत्तर से अधिक टिप्पणी है, लेकिन टिप्पणी फ़ील्ड में फिट नहीं हो सकता है। मेरे पास loosely related question है और parent.env<- की सीमाओं को बेहतर ढंग से समझने की कोशिश कर रहा है।

अपने मामले में, ध्यान दें कि समस्या वास्तव में list2env से संबंधित है, फ़ंक्शन नहीं। पर विचार करें:

f.1 <- function() NULL 
ns.1 <- new.env(parent = .BaseNamespaceEnv) 
x.1 <- new.env(parent = as.environment(2)) 
environment(f.1) <- ns.1 
x.1$f.1 <- f.1 
parent.env(.GlobalEnv) <- x.1 
detach() 

काम करता है, लेकिन:

x.2 <- list2env(list(a=1), parent=as.environment(2)) 
parent.env(.GlobalEnv) <- x.2 
detach() 

दुर्घटनाओं। यहां, हम किसी भी माता-पिता के रूप में उपयोग किए जाने वाले पर्यावरण के साथ कुछ भी जटिल नहीं कर रहे हैं, इसके अलावा इसे list2env के साथ बनाया गया था।स्रोत को देखते हुए मुझे कुछ भी स्पष्ट नहीं दिख रहा है कि क्यों list2env एक समस्या है लेकिन $<- आंतरिक रूप से defineVar का उपयोग करने लगते हैं, लेकिन स्पष्ट रूप से वहां बहुत कुछ चल रहा है जो मुझे समझ में नहीं आता है।

+0

मैं सराहना करता हूं ... "टिप्पणी"। इसके लायक होने के लिए, टिप्पणियों में जुड़े एक [निजी चैट रूम] (http://chat.stackoverflow.com/), शायद इसके लिए एक बेहतर जगह होगी। हालांकि, मुझे लगता है कि यह टिप्पणी उत्तर के रूप में रहने के लिए पर्याप्त योगदान है, भले ही यह वास्तव में इस मुद्दे को हल न करे। यह महत्वपूर्ण जानकारी का योगदान करता है। –

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