से उल्लंघन उल्लंघन अपवाद/क्रैश एक्सेस करें इसलिए मेरे पास मूल तृतीय पक्ष सी ++ कोड बेस है (मैं .lib और .hpp फ़ाइलें) के साथ काम कर रहा हूं जिसे मैं अंतिम उपयोग के लिए सी ++/सीएलआई में एक रैपर बनाने के लिए उपयोग करता था सी # मेंसी ++ कॉलबैक से सी # फ़ंक्शन
डीबग से रिलीज मोड में स्विच करते समय मैंने एक विशेष समस्या में भाग लिया है, जिसमें मुझे कॉलबैक कोड वापस आने पर एक्सेस उल्लंघन उल्लंघन प्राप्त होता है।
कॉलबैक फ़ंक्शन प्रारूप के लिए मूल HPP फाइलों से कोड:
typedef int (*CallbackFunction) (void *inst, const void *data);
C++/CLI आवरण के कॉलबैक समारोह प्रारूप के लिए कोड: (मैं समझाऊंगा कारण है कि मैं एक पल में दो घोषित)
public delegate int ManagedCallbackFunction (IntPtr oInst, const IntPtr oData);
public delegate int UnManagedCallbackFunction (void* inst, const void* data);
--Quickly, कारण मैं घोषित एक दूसरे "UnManagedCallbackFunction" है कि मैं आवरण में एक "मध्यस्थ" कॉलबैक बनाने की कोशिश की है, इसलिए श्रृंखला मूल निवासी सी ++> का एक संस्करण से मूल निवासी सी ++> सी # बदला सी ++/सीएलआई रैपर> सी # ... पूर्ण प्रकटीकरण ठीक है, समस्या अभी भी जीवित है, इसे अभी सी ++/सीएलआई रैपर को उसी पंक्ति (वापसी) पर धकेल दिया गया है।
और अंत में, सी # से क्रैश होने कोड:
public static int hReceiveLogEvent(IntPtr pInstance, IntPtr pData)
{
Console.WriteLine("in hReceiveLogEvent...");
Console.WriteLine("pInstance: {0}", pInstance);
Console.WriteLine("pData: {0}", pData);
// provide object context for static member function
helloworld hw = (helloworld)GCHandle.FromIntPtr(pInstance).Target;
if (hw == null || pData == null)
{
Console.WriteLine("hReceiveLogEvent: received null instance pointer or null data\n");
return 0;
}
// typecast data to DataLogger object ptr
IntPtr ip2 = GCHandle.ToIntPtr(GCHandle.Alloc(new DataLoggerWrap(pData)));
DataLoggerWrap dlw = (DataLoggerWrap)GCHandle.FromIntPtr(ip2).Target;
//Do Logging Stuff
Console.WriteLine("exiting hReceiveLogEvent...");
Console.WriteLine("pInstance: {0}", pInstance);
Console.WriteLine("pData: {0}", pData);
Console.WriteLine("Setting pData to zero...");
pData = IntPtr.Zero;
pInstance = IntPtr.Zero;
Console.WriteLine("pData: {0}", pData);
Console.WriteLine("pInstance: {0}", pInstance);
return 1;
}
सभी कंसोल के लिए लिखते हैं किया हैं और फिर हम खतरनाक वापसी पर दुर्घटना देखें: में 0x04d1004c पर
क्रिया के अपवाद helloworld.exe: 0xC0000005: एक्सेस उल्लंघन पढ़ने स्थान 0x04d1004c।
तो मैं यहाँ से डिबगर में कदम, सब मैं देख कॉल स्टैक पर अंतिम प्रविष्टि है:> "04d1004c()", जिनमें से दशमलव मान का मूल्यांकन: 80805964
है कौन सा केवल दिलचस्प यदि आप कंसोल है जो दिखाता है पर नज़र डालें:
entering registerDataLogger
pointer to callback handle: 790848
fp for callback: 2631370
pointer to inst: 790844
in hReceiveLogEvent...
pInstance: 790844
pData: 80805964
exiting hReceiveLogEvent...
pInstance: 790844
pData: 80805964
Setting pData to zero...
pData: 0
pInstance: 0
अब, मुझे पता है डिबग के बीच और जारी कुछ चीजें माइक्रोसॉफ्ट दुनिया में काफी अलग हैं कि। मैं निश्चित रूप से बाइट पैडिंग और चर के प्रारंभिकरण के बारे में चिंतित हूं, इसलिए यदि कुछ ऐसा है जो मैं यहां प्रदान नहीं कर रहा हूं, तो बस मुझे बताएं और मैं (पहले से ही लंबी) पोस्ट में जोड़ दूंगा। मुझे यह भी लगता है कि प्रबंधित कोड सभी स्वामित्व को जारी नहीं कर सकता है और उसके बाद देशी सी ++ सामान (जिसके पास मेरे पास कोड नहीं है) पीडीएटी ऑब्जेक्ट को हटाने या मारने का प्रयास कर रहा है, इस प्रकार ऐप को क्रैश कर रहा है।
अधिक पूर्ण प्रकटीकरण, यह सब डीबग मोड में ठीक (प्रतीत होता है) काम करता है!
एक वास्तविक सिर स्क्रैच समस्या जो किसी भी मदद की सराहना करेगी!
समर्थन के लिए, यह अधिकतर सही था। तीसरे पक्ष के विक्रेता से संपर्क करने के बाद, हमने पाया कि वे सीडीसीएल स्पेक का उपयोग करके संकलित किए गए हैं और प्रबंधित कोड अनुपालन के लिए आवश्यक स्टडकॉल नहीं: http://msdn.microsoft.com/en-us/library/367eeye0%28VS.80%29.aspx । मैंने StackOverflow पर एक प्रश्न पूछा कि यह क्यों होना चाहिए? उम्मीद है कि, संदर्भित एमएसडीएन लेख की तुलना में कोई बेहतर स्पष्टीकरण देगा। – TomO
प्रोजेक्ट सेटिंग्स में कॉलिंग कन्वेंशन (सी/सी ++) के लिए डिफ़ॉल्ट है यदि __declspec() के साथ निर्दिष्ट नहीं है। कोड में यह कॉलिंग सम्मेलन दिखाई नहीं दे रहा था। मिस्चैचिंग सम्मेलनों के साथ क्या होता है यह स्पष्ट है: यदि स्टैक क्लीनअप की ज़िम्मेदारी मेल नहीं खाती है, तो यह स्टैक को क्रश करता है (कॉल से पहले अपने राज्य में रीसेट नहीं होता क्योंकि डबल क्लीनअप या बहुत कम)। यह ढेर पर पारित तर्कों की मात्रा पर निर्भर करता है। http://en.wikipedia.org/wiki/Calling_convention – jdehaan