मुझे एक फ़ंक्शन की आवश्यकता है जो (WinAPI से SecureZeroMemory की तरह) हमेशा मेमोरी को शून्य करता है और दूर अनुकूलित नहीं होता है, भले ही कंपाइलर को लगता है कि मेमोरी उसके बाद फिर से एक्सेस नहीं होने वाली है। अस्थिर के लिए एक आदर्श उम्मीदवार की तरह लगता है। लेकिन मुझे वास्तव में जीसीसी के साथ काम करने के लिए कुछ समस्याएं हो रही हैं। यहाँ एक उदाहरण समारोह है:
void volatileZeroMemory(volatile void* ptr, unsigned long long size)
{
volatile unsigned char* bytePtr = (volatile unsigned char*)ptr;
while (size--)
{
*bytePtr++ = 0;
}
}
काफी सरल। लेकिन कोड जिसे जीसीसी वास्तव में उत्पन्न करता है अगर आप कहते हैं कि यह संकलक संस्करण के साथ बेतहाशा भिन्न होता है और आप वास्तव में शून्य करने की कोशिश कर रहे हैं तो बाइट्स की मात्रा। https://godbolt.org/g/cMaQm2
- जीसीसी 4.4.7 और 4.5.3 कभी भी अस्थिरता को नजरअंदाज नहीं करते हैं।
- जीसीसी 4.6.4 और 4.7.3 सरणी आकार 1, 2 और 4 के लिए अस्थिरता को अनदेखा करते हैं।
- 4.9.2 तक जीसीसी 4.8.1 सरणी आकार 1 और 2 के लिए अस्थिरता को नजरअंदाज करता है।
- जीसीसी 5.1 तक सरणी आकार 1, 2, 4, 8 के लिए वाष्पशील को अनदेखा करें।
- GCC 6.1 केवल किसी भी सरणी आकार (स्थिरता के लिए बोनस अंक) के लिए इसे अनदेखा करता है।
किसी भी अन्य संकलक का मैंने परीक्षण किया है (क्लैंग, आईसीसी, वीसी) उन स्टोरों को उत्पन्न करता है जिनकी कोई अपेक्षा होती है, किसी भी संकलक संस्करण और किसी भी सरणी आकार के साथ। तो इस बिंदु पर मैं सोच रहा हूं, क्या यह एक (बहुत पुराना और गंभीर?) जीसीसी संकलक बग है, या मानक में अस्थिरता की परिभाषा है जो यह आरोप लगाता है कि यह वास्तव में व्यवहार के अनुरूप है, जिससे पोर्टेबल लिखना अनिवार्य रूप से असंभव है " SecureZeroMemory "फ़ंक्शन?
संपादित करें: कुछ दिलचस्प अवलोकन।
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <atomic>
void callMeMaybe(char* buf);
void volatileZeroMemory(volatile void* ptr, std::size_t size)
{
for (auto bytePtr = static_cast<volatile std::uint8_t*>(ptr); size-- > 0; )
{
*bytePtr++ = 0;
}
//std::atomic_thread_fence(std::memory_order_release);
}
std::size_t foo()
{
char arr[8];
callMeMaybe(arr);
volatileZeroMemory(arr, sizeof arr);
return sizeof arr;
}
CallMeMaybe () से संभव लेखन 6.1 को छोड़कर सभी जीसीसी संस्करण बना देगा अपेक्षित भंडार। मेमोरी बाड़ में टिप्पणी करने से जीसीसी 6.1 भी स्टोर बनाएगा, हालांकि केवल कॉलमैये से संभावित लेखन के संयोजन में ()।
किसी ने भी कैश फ्लश करने का सुझाव दिया है। Microsoft "SecureZeroMemory" में कैश को फ्लश करने की कोशिश नहीं करता है । कैश के वैसे भी बहुत तेजी से अमान्य होने की संभावना है, इसलिए यह शायद एक बड़ी बात नहीं है। इसके अलावा, यदि कोई अन्य प्रोग्राम डेटा की जांच करने की कोशिश कर रहा है, या यदि यह पेज फ़ाइल में लिखा जा रहा है, तो यह हमेशा शून्य संस्करण होगा।
स्टैंडअलोन फ़ंक्शन में मेमसेट () का उपयोग करके जीसीसी 6.1 के बारे में कुछ चिंताएं भी हैं। कुछ लोगों के लिए स्टैंडअलोन फ़ंक्शन के लिए GCC 6.1 कंपाइलर एक टूटे हुए बिल्ड का निर्माण कर सकता है, क्योंकि GCC 6.1 एक सामान्य लूप (जैसे 5.3 गॉडबोल्ट पर करता है) उत्पन्न करता है। (Zwol के जवाब की टिप्पणियाँ पढ़ें।)
volatile
करना बग है जब तक कि अन्यथा सिद्ध न हो। लेकिन सबसे अधिक संभावना एक बग है।volatile
इतना अस्वाभाविक है जितना खतरनाक हो - बस इसका उपयोग न करें।