2013-07-30 7 views
7

पर मेमसेट के बारे में समय चेतावनी संकलित करें मैं एक बड़े कोड बेस पर काम कर रहा हूं, कुछ पुराने सी मॉड्यूल को C++ में परिवर्तित कर रहा हूं। मैं एक संरचना में एक सी ++ ऑब्जेक्ट जोड़ना चाहता हूं, लेकिन इस संरचना के कुछ उपयोगकर्ता memset इसे, जो ऑब्जेक्ट के लिए दुर्भाग्यपूर्ण है जिसे मैं संरचना में रखना चाहता हूं।गैर सादे पुराने डेटा

यह कैसे किया जा रहा है संकलन समय पर मैं कैसे पता लगा सकता हूं, ताकि मैं इस तरह की संरचना पर memset के सभी उपयोग को खत्म कर सकूं जो अब पीओडी नहीं है?

+0

क्या 'memset' के लिए grep'ing मैन्युअल रूप से जांचने के लिए बहुत सारे परिणाम बदलता है? अन्यथा, मुझे यह जांचने के लिए कंपाइलर के लिए कोई रास्ता नहीं दिख रहा है। – arne

+0

@arne समस्या का हिस्सा है, हां। – Henrik

उत्तर

8

मुझे यकीन नहीं है कि संकलक सीधे कुछ संकलन झंडे प्रदान करके आपकी सहायता करेगा या नहीं। यदि यह करता है, तो आपके लिए अच्छा है। उसका उपयोग करें। कहानी का अंत।

यदि ऐसा नहीं होता है, तो शायद यह आपकी मदद करेगा। चूंकि आप अपना कोड सी से सी ++ में परिवर्तित कर रहे हैं, इसका मतलब है कि मेमसेट के सभी उपयोग std:: नेमस्पेस के बिना हैं। तो और इस तथ्य का लाभ लेने के #define memset के रूप में:

#define memset memset_if_pod_else_error() 

यहाँ memset_if_pod_else_error एक समारोह आपके द्वारा लिखा है (यानी आप इसे लागू करने के लिए है)। आप इसे टेम्पलेट बना सकते हैं ताकि तर्क के प्रकार को कम किया जा सके और फिर यह पता लगाया जा सके कि प्रकार पीओडी है या नहीं। यदि यह पीओडी है, तो यह ठीक है और std::memset आंतरिक रूप से कॉल करें, अन्यथा त्रुटि बढ़ाएं।

मेटाफंक्शन जैसे std::enable_if और std::is_pod इस फ़ंक्शन को लागू करने में आपकी सहायता करेंगे।

यहाँ इस विचार का एक न्यूनतम डेमो है:

#include <iostream> 
#include <type_traits> 
#include <cstring> 

auto ptr_memset = std::memset; //store this a pointer 

template<typename T> 
using VoidPtr = typename std::enable_if<std::is_pod<T>::value, void*>::type; 

#define memset memset_if_pod_else_error 

template<typename T> 
VoidPtr<T> memset_if_pod_else_error(T *data, int ch, size_t count) 
{ 
     return ptr_memset(data, ch, count); 
} 

struct pod {}; 
struct nonpod { nonpod() {} }; 

int main() 
{ 
    pod p; 
    nonpod np; 

    memset(&p, 0, sizeof(p)); 

    memset(&np, 0, sizeof(np)); //this is error! 
} 

memset को दूसरी कॉल इस त्रुटि उत्पन्न करता है:

error: no matching function for call to 'memset_if_pod_else_error'
memset(&np, 0, sizeof(np));
^~~~~~

Online Demo

आशा है कि मदद करता है।

+0

धन्यवाद, यह एक अच्छा विचार है। पुराने सी मॉड्यूल को नए सी ++ कोड में हजारों स्थानों का भी उपयोग किया जाता है, इसलिए दुर्भाग्यवश मेरे लिए यह केवल मेरी समस्या को आंशिक रूप से हल करेगा। – Henrik

+0

@ हेनरिक: मुझे कोई समस्या नहीं दिख रही है। आप तदनुसार फ़ंक्शन को कार्यान्वित कर सकते हैं। मेरा डेमो देखें। उम्मीद है कि आपके * बेहतर * विचार देता है। – Nawaz

1

मुझे नहीं लगता कि आप संकलन समय पर गैर-पीओडी डेटा पर memset का उपयोग कर सकते हैं।

आप क्या कर सकते हैं कुछ अतिरिक्त फ़ील्ड जो कि कन्स्ट्रक्टर में सेट है, और उसके बाद किसी अन्य सदस्य फ़ंक्शन में चेक किया गया है। कुछ ऐसा:

class X 
{ 
    const int MAGIC = 123456789; 
    int magic; 
    ... 
    public: 
    X() : magic(MAGIC) { ... } 
    ... 
    void do_stuff() 
    { 
     check_magic(); 
     ... 
    } 
    private: 
    void check_magic() 
    { 
     if (magic != MAGIC) { ... do something to indicate bad state ... }; 
    } 
}; 

जाहिर है, यह "केवल डीबग बिल्ड पर" किया जा सकता है।

+0

यदि निर्माता को 'constexpr' बनाया जा सकता है, तो क्या इसे स्थिर दावे से भी जांच नहीं किया जा सकता है? – arne

+0

समस्या निर्माण में नहीं है, समस्या यह है कि 'मेमसेट' वास्तव में उस परवाह नहीं करता है जिसे आप इसमें खिला रहे हैं, और आप जो कुछ भी खिलाते हैं उस पर सीधे विभाजित करेंगे - जिसका मतलब है कि आपको जांचना है 'जादू' के बाद 'संभावित कॉल)' स्मृति '। –

2

कैसे इस बारे में:

auto orig_memset = std::memset; 
#define memset checked_memset 

template <class T> 
void* checked_memset(T* ptr, int value, size_t num) { 
    static_assert(std::is_pod<T>::value, "memset on non-POD"); 
    return original_memset(data, value, num); 
} 

या, यदि आप केवल अपने विशेष struct के लिए उल्लंघन की खोज में रुचि रखते हैं: सब समस्या क्षेत्रों को खोजने के लिए

auto original_memset = std::memset; 
#define memset checked_memset 

template <class T> 
void* checked_memset(T* ptr, int value, size_t num) { 
    static_assert(!std::is_same<T, YOUR_STRUCT_HERE>::value, "memset used on YOUR_STRUCT_HERE"); 
    return original_memset(data, value, num); 
} 
+0

रिटर्न प्रकार शायद शून्य * होना चाहिए, टी नहीं। – wolfgang

+0

उचित बिंदु, धन्यवाद। –

0

कोशिश कर के इस मामले isntead में , मैं सिर्फ उन्हें पहले स्थान पर रोकने का सुझाव दूंगा। विशेष रूप से, मौजूदा सी structs पर किसी भी C++ क्षमताओं को न जोड़ें, बल्कि इसके बजाय कक्षाओं को एक उचित इंटरफेस के साथ लिखें जिसमें सी डेटा संरचनाओं के उदाहरण शामिल हों। फिर आप पुरानी संरचनाओं और कोड के साथ-साथ नई सी ++ क्षमताओं को जोड़ते हुए कुल पिछड़ा संगतता बनाए रखते हैं।

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