2012-07-15 26 views
6

इस प्रश्न की चर्चा से How is access for private variables implemented in C++ under the hood? मैंने एक भिन्नता उत्पन्न की: एक निजी डेटा सदस्य तक पहुंचने के बजाय, क्या कोई लेआउट-संगतता पर कास्टिंग और भरोसा करके निजी सदस्य कार्यों को कॉल कर सकता है?क्या कोई लेआउट-संगत प्रकारों को कास्टिंग के माध्यम से निजी सदस्य कार्यों तक पहुंच सकता है?

कुछ कोड

#include <iostream> 

class X 
{ 
public: 
    X() : private_(1) { /*...*/ } 

private: 
    int Value() { return private_; } 
    int private_; 
}; 

// Nasty attempt to simulate the object layout 
// (cross your fingers and toes). 
// 
class BaitAndSwitch 
    // hopefully has the same data layout as X 
{ // so we can pass him off as one 
public: 
    int Value() { return private_; } 
private: 
    int private_; 
}; 

int f(X& x) 
{ 
    // evil laughter here 
    return (reinterpret_cast<BaitAndSwitch&>(x)).Value(); 
} 

int main() 
{ 
    X x; 
    std::cout << f(x) << "\n"; // prints 0, not 1 
    return 0; 
}; 

नोट (हर्ब सुतर की स्तंभ Uses and Abuses of Access Rights से प्रेरित): इस काम करता है (कम से कम Ideone पर)! क्या कोई नया तरीका है C++11 Standardगारंटी या कम से कम कार्यान्वयन-परिभाषित लेआउट-संगतता और reinterpret_cast/static_cast पर भरोसा करके अभिगम नियंत्रण को रोकने के लिए तरीका देता है?

EDIT1: सुतर की स्तंभ में उन्होंने दो कारण हैं जिनकी वजह से ऊपर कोड काम करने के लिए गारंटी नहीं है सूचीबद्ध करता है (हालांकि यह व्यवहार में काम करता है)

एक): Ideone

EDIT2 पर उत्पादन एक्स और बैट एंड स्विच के ऑब्जेक्ट लेआउट को होने की गारंटी नहीं है, हालांकि व्यवहार में वे शायद हमेशा होंगे।

ख) reinterpret_cast के परिणामों अपरिभाषित कर रहे हैं, हालांकि ज्यादातर compilers दूँगी आप जिस तरह से हैकर का इरादा है, जिसके परिणामस्वरूप संदर्भ का उपयोग करने का प्रयास करें।

क्या नया सी ++ 11 मानक अब इन लेआउट/reinterpret_cast गारंटी प्रदान करता है?

+0

आप 'reinterpret_cast'' के साथ जो कुछ भी चाहते हैं उसे बाधित कर सकते हैं; क्या आप पूछ रहे हैं कि एक अच्छी तरह से परिभाषित तरीके से ऐसा करना संभव है? –

+0

@ ओली चार्ल्सवर्थ हां, गारंटी सबसे अच्छी होगी, कार्यान्वयन परिभाषित दूसरा सर्वश्रेष्ठ और यूबी इतना अच्छा नहीं है। – TemplateRex

+0

कोई रास्ता नहीं। असेंबली लेवल क्लास विधि पर छुपा "यह" पैरामीटर के साथ सिर्फ वैश्विक कार्य है, यह क्लास इंस्टेंस से संबंधित नहीं है और इसे लेआउट ट्रिक्स के माध्यम से एक्सेस नहीं किया जा सकता है। –

उत्तर

3

हां, आप एक प्रकार का निर्माण कर सकते हैं जो उस प्रकार के लेआउट का उपयोग करता है, जिस प्रकार से आप चोरी करने का प्रयास कर रहे हैं, फिर reinterpret_cast उस प्रकार से अपने लेआउट संगत प्रकार पर। लेकिन यह केवल मानक द्वारा संरक्षित है यदि दोनों स्रोत और गंतव्य प्रकार मानक लेआउट प्रकार हैं (और बेशक, यह वास्तव में काम करता है यदि उनके लेआउट समान हैं)। तो अगर स्रोत में वर्चुअल फ़ंक्शन हैं, तो आप खराब हो गए हैं।

ऐसा लगता है कि यहां सटर के दोनों मुद्दों को पूरा किया गया है। मानक लेआउट के नियम यह सुनिश्चित करते हैं कि दो प्रकार के मानक लेआउट दोनों एक ही क्रम में समान सदस्यों को परिभाषित करते हैं, लेआउट-संगत (सेक्शन 9.2, अनुच्छेद 17):

दो मानक-लेआउट संरचना (क्लॉज 9) प्रकार लेआउट-संगत होते हैं यदि उनके पास समान संख्या में गैर-स्थैतिक डेटा सदस्य हैं और संबंधित गैर-स्थैतिक डेटा सदस्य (घोषणा क्रम में) में लेआउट-संगत प्रकार (3.9) हैं।

और reinterpret_cast के लिए नियमों को दो मानक लेआउट प्रकार (अनुभाग 5.2.10, पैरा 7) के बीच रूपांतरण के अर्थ निर्दिष्ट करें:

एक वस्तु सूचक स्पष्ट रूप से की एक वस्तु सूचक में बदला जा सकता एक अलग प्रकार जब "पॉइंटर टू टी 1" प्रकार का एक प्रवर्तन बनाम "पॉइंटर से सीवी टी 2" प्रकार में परिवर्तित हो जाता है, तो परिणाम static_cast<cv T2*>(static_cast<cv void*>(v)) होता है यदि टी 1 और टी 2 दोनों मानक-लेआउट प्रकार (3.9) हैं और टी 2 की संरेखण आवश्यकताएं कोई कठोर नहीं हैं टी 1 की तुलना में, या यदि कोई भी प्रकार शून्य है।

+0

धन्यवाद, पहले ही गायब रिटर्न स्टेटमेंट को ठीक कर दिया गया है। – TemplateRex

+2

क्या सख्त एलियासिंग का उल्लंघन नहीं करता है? – Puppy

+0

@DeadMG: मुझे यकीन नहीं है। मैंने [मानक में से कुछ वर्गों को देखा जो सख्त एलियासिंग का कारण बनते हैं] (http://stackoverflow.com/a/9588075/734069), और ऐसा लगता है कि यह उनका उल्लंघन नहीं करता है। लेकिन मैं इस पर एक विशेषज्ञ नहीं हूँ। –