2017-02-09 9 views
9

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

मेरा प्रश्न है, क्या निम्न कोड सही है? ऐसा लगता है कि array को आवंटित सरणी स्वचालित रूप से कुछ आर्किटेक्चर पर स्मृति आवंटित कर रही है, लेकिन दूसरों पर नहीं। क्या यहां काम पर कार्यान्वयन विशिष्ट विवरण हैं?

#include <stdlib.h> 

void assign_array_(double x[], int* n); 
void print_array_(); 

int main() 
{ 
    int n,i; 
    double *x; 

    n = 5; 
    x = (double*) malloc(sizeof(double)*n); 

    for (i = 0; i < n; i++) 
     x[i] = (double) i; 

    assign_array_(x,&n); 
    print_array_(); 

    return 0; 
} 

और फोरट्रान कोड:

MODULE test_mod 
    DOUBLE PRECISION, ALLOCATABLE, DIMENSION(:) :: array 
    integer :: nsize 
END MODULE test_mod 

SUBROUTINE assign_array(x,n) 
    USE test_mod 
    IMPLICIT NONE 

    INTEGER :: n 
    DOUBLE PRECISION :: x(n) 

    CALL test_allocated() 
    array = x 
    CALL test_allocated() 
    nsize = n 

END SUBROUTINE assign_array 


SUBROUTINE print_array() 
    USE test_mod, ONLY: nsize, array 
    IMPLICIT NONE 

    INTEGER :: i 

    DO i = 1,nsize 
    WRITE(6,'(F24.16)') array(i) 
    END DO 

END SUBROUTINE print_array 

SUBROUTINE test_allocated() 
    USE test_mod 
    IMPLICIT NONE 

    IF (ALLOCATED(array)) THEN 
    WRITE(6,*) 'Array is allocated' 
    WRITE(6,*) 'size is ', SIZE(array) 
    ELSE 
    WRITE(6,*) 'Array is NOT allocated' 
    END IF 
END SUBROUTINE test_allocated 

निर्गम (जब यह चलता है) है:

Array is NOT allocated 
Array is allocated 
size is   5 
    0.0000000000000000 
    1.0000000000000000 
    2.0000000000000000 
    3.0000000000000000 
    4.0000000000000000 

और

कोड एक मिश्रित सी/फोरट्रान कोड है यहां पावर पीसी पर आउटपुट है:

Array is NOT allocated 
Segmentation fault (core dumped) 

संक्षेप में: यह जीएनयू (जीएनयू फोरट्रान (मैकपॉर्ट्स जीसीसी 5 5.4.0_0) 5.4.0) के तहत संकलित करते समय चलाता है ओएसएक्स (आर्क: x86_64h) और लिनक्स (ओएसएक्स, जीएनयू फोरट्रान (उबंटू) पर होस्ट की गई वर्चुअल मशीन में 4.9.4-2ubuntu1 ~ 14.04.1) 4.9.4), लेकिन जीएनयू फोरट्रान (जीसीसी) 4.4.7 20120313 (Red Hat 4.4.7-17) का उपयोग करके संकलित पावर पीसी (आर्क: पीपीसी 64) पर संकलित होने पर चलाने में विफल रहता है। । हमारे मूल कोड में, पावर पीसी कार्यान्वयन केवल बाद में कोड में segfaulted, जहां सरणी प्रविष्टियों सरणी संदर्भित किया गया था, हमारी 'बग' (अगर यह वास्तव में एक बग है) बनाने के लिए वास्तव में मुश्किल है।

उपरोक्त कोड के लिए सही व्यवहार क्या है?

+0

आप यह जांच नहीं रहे हैं कि मॉलोक सफल होता है या नहीं। – stark

+0

मैंने अभी एक चेक जोड़ा और सभी मामलों में मॉलोक सफल हुआ। – Donna

+1

यदि सरणी आवंटित नहीं की जाती है तो 'array = x' अवैध है। – stark

उत्तर

2

यह पता चला है कि केवल जीएनयू gfortran 4.6 और ऊपर F90 में एलएचएस सरणी के स्वचालित पुनर्वितरण की अनुमति देता है। कंपाइलर ध्वज का उपयोग -fno-realloc-lhs इस सुविधा को अक्षम करता है और सीजी ट्रिगर करता है। मैंने ऊपर वर्णित सभी मामलों में दोष (ओएसएक्स, लिनक्स, पीपीसी) रहस्य हल हो गया! रहस्य पोस्टर के लिए धन्यवाद जिसका टिप्पणी रहस्यमय तरीके से गायब हो गया।

देखें GCC 4.6 Wiki

+1

नहीं, वे इसे F90 में अनुमति नहीं देते हैं, अगर आप सख्त फोरट्रान 95 के साथ संकलित करते हैं तो इसका उपयोग नहीं किया जाना चाहिए। यह एक फोरट्रान ** 2003 ** सुविधा है, जैसा कि फ्रांसेस्लस द्वारा समझाया गया है। यदि आपका मतलब '.90 9 0 फाइलों में है तो हाँ, लेकिन इसका मतलब फोरट्रान 90. –

+0

हां - मेरा मतलब था .f90 फाइलें। मैं 'gfortran' कंपाइलर (gcc5) का उपयोग कर रहा हूं, जिसमें मुझे लगता है कि नवीनतम f95, 2003, और मानकों से परे है। – Donna

+2

एक भेद - यदि कोड किसी विशेष मानक के नियमों के अनुरूप नहीं है, तो मानक निर्दिष्ट नहीं करता है कि क्या होता है, जिसका अर्थ है कि "सही व्यवहार" के संदर्भ में - ** कुछ भी हो सकता है **। "कुछ भी" में प्रोग्राम क्रैशिंग, या प्रोग्राम कुछ प्रकार के जादू पुनर्वितरण, या कार्यक्रम को आपके मालिक को फर्जी इस्तीफा पत्र लिखने और फिर अपने पति/पत्नी के साथ छेड़छाड़ करने का कार्यक्रम शामिल हो सकता है। (वास्तव में क्या होने की संभावना है एक अलग सवाल है।) – IanH

15

तरह

integer, allocatable :: array(:) 
array = (/1,2,3/) 
end 

कोड की वैधता फोरट्रान के मानक पर निर्भर करता है यह समझने के लिये।

फोरट्रान 2003 ने आंतरिक असाइनमेंट पर स्वचालित आवंटन की अवधारणा पेश की। फोरट्रान 2003 से पहले इस तरह के असाइनमेंट कथन के बाईं ओर सरणी आवंटित की जानी चाहिए, और दाहिने हाथ की सरणी के समान आकार के लिए।

फोरट्रान 2003 से केवल रैंक की आवश्यकता है। यदि कोई आकार मेल नहीं खाता है, तो सरणी को पहले हटा दिया जाएगा और फिर सही आकार में फिर से आवंटित किया जाएगा। अगर शुरू में आवंटित नहीं किया जाता है, तो इसे आवंटित किया जाएगा।

तो, कार्यक्रम ऊपर वैध फोरट्रान 90 नहीं है, लेकिन वैध फोरट्रान 2003

वास्तविक दुनिया कोड में अंतर है, तो, क्या भाषा वाक्यविन्यास compilers समर्थन से है।

गोरफ्रान के लिए, फोरट्रान 2003 का आवंटन सरणी को असाइनमेंट introduced in 4.6, 2011-01-28 था।

के रूप में भी टिप्पणी की, आदेश पंक्ति विकल्प -fno-realloc-lhs अक्षम कर देता है यह स्वत: (पुनः) आवंटन, बनाने संकलक 2003+ अनुरूप फोरट्रान नहीं।


अन्य compilers समान व्यवहार किया है: कि क्या पुनः आबंटन के लिए आवश्यक है के लिए एक आवश्यक जाँच जोड़ने एक प्रदर्शन हिट जो फोरट्रान 90 अनुरूप कोड में अनावश्यक है और यहां तक ​​कि आधुनिक कोड में कई द्वारा इस्तेमाल नहीं एक सुविधा हो सकता है । Intel's compiler के लिए, उदाहरण के लिए, F2003 का समर्थन करने वाले कुछ संस्करणों में डिफ़ॉल्ट को अनदेखा करना है।

हमेशा दबा सकती हैं (फिर से) आवंटन चेक/एक सरणी अनुभाग

array(:) = (/1,2,3/) 

का उपयोग कर इस मामले में द्वारा आधुनिक कोड में एक सरणी के कार्यों, array (यदि allocatable) आवंटित किया जाना चाहिए, रैंक के असाइनमेंट स्टेटमेंट के लिए वैध होने के लिए 1 और आकार 3। यह पूरे सरणी array=(/1,2,3/) के साथ असाइनमेंट की फोरट्रान 90 व्याख्या के तहत होगा।

इसका कारण यह है कि इस फुटनोट के सरणी भाग के साथ, बाएं हाथ की तरफ आवंटित नहीं है, भले ही सरणी स्वयं है।