2012-05-04 14 views
5

मैं एक टेम्पलेट वर्ग के रूप में परिभाषित किया है:सी ++ "नया टी [आकार]" काम नहीं करता है?

#include <stdio.h> 
#include <queue> 

using namespace std; 

template<class T> 
class tbufferpool { 
private: 
    const int m_initial; 
    const int m_size; 
    const int m_total; 
    T *m_buffer; 
    vector<T*> m_queue; 

public: 
    // constructor 
    tbufferpool(int initial, int size) : m_initial(initial), m_size(size), m_total(initial*size) { 
     m_buffer = new T[m_total]; 
     T* next_buffer = m_buffer; 
     for (int i = 0; i < initial; ++i, next_buffer += size) { 
      m_queue.push_back(next_buffer); 
     } 
    } 

और निर्माता में कुछ बिंदु पर मैं करता हूँ:

m_buffer = new T[size]; 

यह सबसे उपयोग-मामले के लिए काम करता है, लेकिन एक परीक्षण में मैं निम्नलिखित स्मृति मिल valgrind (नीचे आदेश और प्रासंगिक स्निपेट) द्वारा रिपोर्ट की गई त्रुटि परीक्षण अभी भी ठीक हो जाता है। रोचक बिट operator new(unsigned long) है जिसका अर्थ है कि यह कंक्रीट टी टाइप I सेटअप "डबल" के लिए आवंटित और संरेखित नहीं है जैसा कि मैंने अपेक्षित था लेकिन unsigned long के लिए? अगर मैं अपने बफरपूल कार्यान्वयन और हार्ड-कोड new double[size] को संशोधित करता हूं तो यह स्मृति त्रुटि दिखाई नहीं देती है, लेकिन निश्चित रूप से मैं केवल tbufferpool<double> के साथ काम करता हूं।

क्या कोई सलाह दे सकता है कि इसे कैसे ठीक किया जाए? new T[size] कानूनी अधिकार होना चाहिए? चूंकि टेम्पलेट पैरामीटर प्री-प्रोसेसर द्वारा संकलित समय पर लागू होता है जो प्रत्येक टेम्पलेट प्रकार के लिए एक नई कक्षा बनाता है। क्या यह एक कंपाइलर बग होगा?

test_matrix 30 परीक्षण मामलों वाला एक सूट है। केवल एक परीक्षण वाल्ग्रिंड में नीचे दिखाए गए समस्या का उत्पादन करता है, फिर भी परीक्षण पास हो जाता है। मैंने फ़ंक्शन कॉल में सभी इनपुट चेक किए हैं, जहां समस्या new T[size] संस्करण का उपयोग करके उत्पन्न होती है और उन्हें new double[size] संस्करण का उपयोग करके उसी इनपुट के साथ मुद्रित किया जाता है। मैं AraxisMerge का उपयोग करके उनकी तुलना करता हूं और वे समान हैं। मुझे डर है कि मेमोरी संरेखण से संबंधित एक समस्या अलग-अलग हो रही है, भले ही मैं टेम्पलेट पैरामीटर या कंक्रीट डबल टाइप का उपयोग करता हूं ...?

$ valgrind --show-reachable=yes --dsymutil=yes --track-origins=yes ./test_matrix 
    [snip] 
    ==3719== Conditional jump or move depends on uninitialised value(s) 
    ==3719== at 0x3BE86C8: mkl_blas_dscal (in /opt/intel/composerxe-2011.4.184/mkl/lib/libmkl_mc3.dylib) 
    ==3719== by 0x432FFFFFFFFFFFFF: ??? 
    ==3719== Uninitialised value was created by a heap allocation 
    ==3719== at 0xD62F: malloc (vg_replace_malloc.c:266) 
    ==3719== by 0x97B15C: operator new(unsigned long) (in /opt/local/lib/gcc46/libstdc++.6.dylib) 
    ==3719== by 0x7FFF5FBFE54F: ??? 
    ==3719== by 0x10014BDBF: ??? 
    ==3719== by 0x7FFF5FBFE58F: ??? 
    ==3719== by 0x97B288: operator new[](unsigned long) (in /opt/local/lib/gcc46/libstdc++.6.dylib) 
    ==3719== by 0x7FFF5FBFE58F: ??? 
    ==3719== by 0x100013853: tbufferpool<double>::tbufferpool(int, int) (bufferpool.h:30) 
    ==3719== by 0x7003FFFFF: ??? 
    ==3719== by 0x100079E7F: ??? (in ./test_matrix) 
    ==3719== by 0x7FFF5FBFE58F: ??? 
    ==3719== by 0x10014BE0F: ??? 
    ==3719== 
    ==3719== Conditional jump or move depends on uninitialised value(s) 
    ==3719== at 0x3BE86CA: mkl_blas_dscal (in /opt/intel/composerxe-2011.4.184/mkl/lib/libmkl_mc3.dylib) 
    ==3719== by 0x432FFFFFFFFFFFFF: ??? 
    ==3719== Uninitialised value was created by a heap allocation 
    ==3719== at 0xD62F: malloc (vg_replace_malloc.c:266) 
    ==3719== by 0x97B15C: operator new(unsigned long) (in /opt/local/lib/gcc46/libstdc++.6.dylib) 
    ==3719== by 0x7FFF5FBFE54F: ??? 
    ==3719== by 0x10014BDBF: ??? 
    ==3719== by 0x7FFF5FBFE58F: ??? 
    ==3719== by 0x97B288: operator new[](unsigned long) (in /opt/local/lib/gcc46/libstdc++.6.dylib) 
    ==3719== by 0x7FFF5FBFE58F: ??? 
    ==3719== by 0x100013853: tbufferpool<double>::tbufferpool(int, int) (bufferpool.h:30) 
    ==3719== by 0x7003FFFFF: ??? 
    ==3719== by 0x100079E7F: ??? (in ./test_matrix) 
    ==3719== by 0x7FFF5FBFE58F: ??? 
    ==3719== by 0x10014BE0F: ??? 
    [snip] 

प्रणाली विवरण:

/Users/bravegag/code/fastcode_project/build_debug$ uname -a && g++ --version 
Darwin Macintosh-4.local 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 18:47:41 PST 2012; 
root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64 
g++ (GCC) 4.6.3 
Copyright (C) 2011 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+0

बस एक विचार है, लेकिन शायद ऐसा इसलिए है क्योंकि 'डबल' 'हस्ताक्षर किए गए लंबे' के समान आकार का है। – Tibor

+3

कृपया समस्या को अलग करने का प्रयास करें (प्रकार के साथ 'tbufferpool' टेम्पलेट का एक तात्कालिकता, कन्स्ट्रक्टर से जितना संभव हो सके हटाएं) और कोड को दोबारा पोस्ट करें। सबसे महत्वपूर्ण यह है कि 'आकार' कैसे शुरू किया जाता है। –

+0

इसका मतलब है कि आपने उस आवंटित स्मृति के कुछ हिस्से को प्रारंभ नहीं किया है, लेकिन आपको इसे करना चाहिए था। क्या आप आवंटित स्मृति को शुरू कर रहे हैं? – mfontanini

उत्तर

4

कृपया

m_buffer = new T[size]; 

और

m_buffer = new T[size](); 

के बीच का अंतर पूर्व के मामले में ध्यान दें सरणी initialised नहीं है, इसलिए अपने valgrind त्रुटि:

Conditional jump or move depends on uninitialised value 

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

+0

वाह शानदार! आपके सुझाव समस्या हल करता है! मैं मैक ओएस एक्स 4.6.3 में जी ++ और जीसीसी नवीनतम संस्करण का उपयोग कर रहा हूं –

2

आपकी समस्या प्रति मेमोरी आवंटन से संबंधित नहीं है। वालग्रिंड का कहना है कि आप m_buffer द्वारा इंगित सरणी से प्रारंभिक मानों का उपयोग कर रहे हैं। आप

 

T value; 
// use value 
 

या

 

T values[size]; 
// use values 
 

के साथ एक ही प्राप्त कर सकते हैं इस मुद्दे को आप स्मृति आवंटन, उदा के बाद उपयुक्त मान के साथ अपने बफर प्रारंभ करने की आवश्यकता होगी ठीक करने के लिए

 

m_buffer = new T[size]; 
std::fill_n(m_buffer, size, T()); 
 
 

m_buffer = new T[size](); // doesn't work in gcc3.x.x 
 

या सिर्फ std :: वेक्टर के बजाय का उपयोग करें।

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