2009-03-11 19 views
14

मुझे मध्य प्रविष्टि से जुड़े निश्चित सरणी में डेटा में हेरफेर करने की आवश्यकता है। memcpy, आदि का उपयोग करने के बजाय। मैं वेक्टर का उपयोग करना चाहता हूँ। जब मुझे वेक्टर तत्वों को वापस सी-शैली सरणी में कॉपी करने के लिए चाहिए तो मुझे समस्या है।std :: vector की सामग्री को सी-स्टाइल स्थिर सरणी में सुरक्षित रूप से कैसे कॉपी करें?

void tryvector() 
{ 
    using namespace std; 
    const int MAX_SIZE=16; 
    BYTE myarr[MAX_SIZE]={0xb0,0x45,0x47,0xba,0x11,0x12, 0x4e}; 
    vector<BYTE> myvec (myarr, myarr+MAX_SIZE); 
    vector<BYTE>::iterator it; 

    printf("myarr pre :"); 
    for(int i=0;i<MAX_SIZE;++i){ 
     printf("%02x ", myarr[i]) ; 

    } 

    printf("\nmyvec pre :") 
    for(it=myvec.begin(); it<myvec.end();++it){ 
     cout<<hex<<static_cast<int>(*it)<<" "; 

    } 

    it = myvec.begin()+ 3; 
    myvec.insert(it,0x5f); 
    printf("\nmyvec post:"); 
    for(it=myvec.begin(); it<myvec.end();++it){ 
     cout<<hex<<static_cast<int>(*it)<<" "; 


    } 

    copy(myvec.begin(), myvec.end(), myarr); //??? 
    printf("\nmyarr post:"); 
    for(int i=0;i<MAX_SIZE;++i){ 
     printf("%02x ", myarr[i]) ; 

    } 

} 

मैं बनाम 2005 यहाँ का उपयोग कर रहा है चेतावनी: कोड यह

warning C4996: 'std::_Copy_opt' was declared deprecated 
1>  c:\program files\microsoft visual studio 8\vc\include\xutility(2270) : see  declaration of 'std::_Copy_opt' 
1>  Message: 'You have used a std:: construct that is not safe. See documentation on how to use the Safe Standard C++ Library' 
1>  c:\documents and settings\mhd\my documents\tesvector.cpp(50) : see reference to function template instantiation '_OutIt std::copy<std::_Vector_iterator<_Ty,_Alloc>,BYTE*>(_InIt,_InIt,_OutIt)' being compiled 
1>  with 
1>  [ 
1>   _OutIt=BYTE *, 
1>   _Ty=BYTE, 
1>   _Alloc=std::allocator<BYTE>, 
1>   _InIt=std::_Vector_iterator<BYTE,std::allocator<BYTE>> 
1>  ] 

जब मैंने इसे चलाने के लिए, मैं निम्नलिखित रन-टाइम त्रुटि मिला:


    Run-Time Check Failure #2 - Stack around the variable 'myarr' was corrupted. 

कृपया ध्यान दें कि मैं वेक्टर के बजाय सूची या डेक का उपयोग करता हूं क्योंकि उपरोक्त कोड की तरह 'मध्य सम्मिलन' एक विशेष जांच है एलईएम। यह 'अंत में डालने' और 'तत्व की यादृच्छिक पहुंच' से कम होगा।
कोई समाधान?

कोई भी उत्तर जैसा दिखता है: "आप सी ++ का उपयोग करते हैं, सी शैली सरणी कार्यान्वयन ड्रॉप करें। सभी सरणी कार्यान्वयन के लिए केवल वेक्टर का उपयोग करें" वास्तव में सहायक नहीं है।

धन्यवाद।

+0

सिर्फ इसलिए कि आप एक सरणी के बजाय वेक्टर <> का उपयोग कर रहे हैं इसका मतलब यह नहीं है कि memcpy() नहीं हो रहा है। वेक्टर <> विधियों को समझना आसान होता है, लेकिन वही काम करते हैं, और प्रदर्शन बड़े सरणी के लिए खराब होगा। – slacy

उत्तर

18

समस्या यह है कि आप वेक्टर में चीजें जोड़ रहे हैं, इसलिए यह myarr सरणी में से अधिक तत्वों के साथ समाप्त होता है जिसे आपने आरंभ किया था। या

myvec.resize(MAX_SIZE); 

आप तत्वों की संख्या तुम वापस कॉपी सीमित हो सकती है:

आप वेक्टर सरणी में वापस की प्रतिलिपि बनाना चाहते हैं, तो आप यह आकार नीचे करने की आवश्यकता होगी

copy(myvec.begin(), myvec.begin()+MAX_SIZE, myarr); 

यदि आप सभी तत्वों को रखने के लिए myarr सरणी चाहते हैं, तो इसे MAX_SIZE से बड़ा होना चाहिए, और आपको पता चला है कि क्यों लोग कच्चे सरणी के बजाय vector का उपयोग करने का सुझाव देते हैं (vector पता है कि कैसे बढ़ना है, सरणी नहीं है) ।

ध्यान दें कि जब आप नहीं चाहते हैं 'कोई भी उत्तर जैसा दिखता है: "आप सी ++ का उपयोग करते हैं, सी शैली सरणी कार्यान्वयन ड्रॉप करें। सभी सरणी कार्यान्वयन के लिए केवल वेक्टर का उपयोग करें", आप अक्सर vector का उपयोग कर दूर हो सकते हैं और कच्चे सरणी की अपेक्षा रखने वाले दिनचर्या के लिए &myvec[0] गुजरना। vector को इस कारण से कच्चे सरणी की तरह अपने तत्वों को व्यवस्थित रूप से स्टोर करने की आवश्यकता है।

चूंकि आपको 'असुरक्षित ऑपरेशन' चेतावनी मिल रही है, इसलिए आप माइक्रोसॉफ्ट के कंपाइलर का उपयोग कर रहे हैं। समस्या को सुरक्षित रूप से ठीक करने के लिए, आपको copy के बजाय checked_copy एल्गोरिदम का उपयोग करना होगा। Evgeny Lazin indicates के रूप में, आप checked_copy एल्गोरिदम पर जाने के लिए अपनी सरणी के लिए एक चेक इटरेटर बना सकते हैं।

कॉपी को सुरक्षित करने के लिए अन्य विकल्प जिन्हें Microsoft एक्सटेंशन की आवश्यकता नहीं है, वे सरणी को एक वर्ग (संभावित रूप से टेम्पलेट) में लपेटना होगा जो सरणी आकार का ट्रैक रखता है और सरणी में डेटा को सुरक्षित तरीके से कॉपी करने के तरीके प्रदान करता है । STLSoft's array_proxy template या Boost's boost::array जैसी कुछ मदद कर सकती है।

+0

हां, यह आपके रनटाइम मुद्दे को हल करता है। –

+0

यह काम करता है, लेकिन चेतावनी अभी भी वहां है। क्या ये ठीक है? – mhd

+0

ध्यान दें कि अब सी ++ 11 के साथ std :: array –

0

आप कर सकते हैं:

memcpy(myarr, &(myvec)[0], myvec.size()) 

संपादित करें: जहाँ तक सुरक्षा की बात है, this के अनुसार, स्मृति से सटे क्षेत्रों में वैक्टर दुकान डेटा है, तो आप उन तक पहुँच "न केवल iterators का उपयोग कर, लेकिन यह भी का उपयोग कर ऑफसेट कर सकते हैं तत्वों के लिए नियमित पॉइंटर्स पर। "

+0

यह वही समस्या होगी क्योंकि myvec.size() myarr से बड़ा है, यदि आप वेक्टर और सरणी के प्रकार को बदलते हैं तो इसका इरादा काम करने की अतिरिक्त समस्या है। –

+0

हां, यह केवल संकलन-समय समस्या को हल करता है। –

+0

यह भी ध्यान रखें कि यदि वे खाली हैं तो वेक्टर के [0] का पता लेना सुरक्षित नहीं है। नए वीसी ++ रनटाइम्स जोर से इस बारे में शिकायत करेंगे (और ठीक है, आईएमएचओ)। –

3

सामान्य तौर पर, मुझे लगता है कि आप कुछ इस तरह कर सकता है:

void *myarr; 

if((myarr = malloc(myvec.size() * sizeof myvec[0])) != NULL) 
{ 
    memcpy(myarr, &myvec[0], myvec.size() * sizeof myvec[0]); 
    /* Do stuff with the C-style array for a while 
    . 
    . 
    . 
    */ 
    free(myarr); /* Don't forget handing back the memory when done. */ 
} 

यह एक नई सी-शैली सरणी वेक्टर के तत्वों धारण करने के लिए आबंटित करता है, और प्रतियां जगह में डेटा। इस तरह से आकारों को स्थिर रूप से मिलान करने की आवश्यकता नहीं है।

बेशक, यह सामान्य है, इसलिए यह आपको अपने सी सरणी तक पहुंचने के लिए void * देता है, इसलिए आपको या तो इस प्रकार में वास्तविक प्रकार (BYTE) को डालने या बदलने के लिए आवश्यक है। अनियंत्रित सामग्री के बारे में माइक्रोसॉफ्ट चेतावनी बंद

template<typename T, size_t N> 
size_t copy(std::vector<T> const& src, T[N] dest) { 
    size_t count = std::min(N, src.size()); 
    std::copy(src.begin(), src.begin()+count, dest); 
    return count; 
} 

बारी:

+0

क्या आप नियमित रूप से इस तरह कोड लिखते हैं? –

+0

आपको तकनीक के लिए C++ – codymanix

1

आप सरणी के लिए बाध्य खोजने के लिए टेम्पलेट तर्क कटौती का उपयोग कर सकते हैं। वे आपको अयोग्य कोड लिखने के लिए लुभाने के उद्देश्य से हैं।

+2

+1 में malloc/free के बजाय नया/हटाएं [] का उपयोग करना चाहिए। लेकिन "आपको अयोग्य कोड लिखने में लुभा रहा है"? एमएस एक अनुरूप कार्यान्वयन प्रदान करता है, वैकल्पिक सुरक्षा सुविधाओं के साथ बढ़ाया जाता है जो बंद करना आसान होता है, और लोग * इसके बारे में * शिकायत करेंगे - अद्भुत। –

+0

चेतावनी में "सुरक्षित मानक सी ++ लाइब्रेरी" का संदर्भ देखें, यह एक मानक नहीं है। इसके पीछे विचार बुरा नहीं है, लेकिन वे नामकरण में सुसंगत होना चाहिए था। जैसे stdext :: check_iterator/है/ठीक से नामित है। – MSalters

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