"অস্থির" এর সংজ্ঞাটি কি এই অস্থির, বা জিসিসির কিছু মানক সংস্করণের সমস্যা রয়েছে?


89

আমার এমন একটি ফাংশন দরকার যা (উইনপিআই থেকে সিকিউরজিরো মেমোরির মতো) সর্বদা স্মৃতি শূন্য করে এবং অপ্টিমাইজড হয় না, যদিও সংকলকটি মনে করে যে এর পরে মেমরিটি আর কখনও অ্যাক্সেস হয় না। অস্থির জন্য নিখুঁত প্রার্থীর মতো মনে হচ্ছে। তবে বাস্তবে এটি জিসিসির সাথে কাজ করার জন্য আমার কিছু সমস্যা হচ্ছে। এখানে একটি উদাহরণ ফাংশন:

void volatileZeroMemory(volatile void* ptr, unsigned long long size)
{
    volatile unsigned char* bytePtr = (volatile unsigned char*)ptr;

    while (size--)
    {
        *bytePtr++ = 0;
    }
}

যথেষ্ট সহজ। আপনি যদি জিসিসি কল করেন তবে জিসিসি আসলে যে কোডটি উত্পন্ন করে তা সংকলক সংস্করণ এবং বাইটের পরিমাণের সাথে আপনি প্রকৃতপক্ষে শূন্য করার চেষ্টা করছেন with https://godbolt.org/g/cMaQm2

  • জিসিসি 4.4.7 এবং 4.5.3 কখনই অস্থিরতাকে উপেক্ষা করে না।
  • GCC 4.6.4 এবং 4.7.3 অ্যারে মাপের 1, 2 এবং 4 এর জন্য অস্থিরতা উপেক্ষা করে।
  • GCC 4.8.1 অবধি 4.9.2 পর্যন্ত অ্যারের আকার 1 এবং 2 এর জন্য অস্থিরতা উপেক্ষা করুন।
  • জিিসিসি 5.1 5.3 অবধি অ্যারে মাপের 1, 2, 4, 8 এর জন্য অস্থিরতা উপেক্ষা করুন।
  • জিসিসি .1.১ এটিকে যে কোনও অ্যারের আকারের জন্য (ধারাবাহিকতার জন্য বোনাস পয়েন্ট) উপেক্ষা করে।

আমি পরীক্ষিত অন্য কোনও সংকলক (ঝনঝন, আইসিসি, ভিসি) যে কোনও স্টোরের প্রত্যাশিত স্টোর তৈরি করে, যে কোনও সংকলক সংস্করণ এবং কোনও অ্যারের আকার সহ। সুতরাং এই মুহুর্তে আমি ভাবছি, এটি কি একটি (বেশ পুরানো এবং গুরুতর?) জিসিসি সংকলক বাগ, বা মানের মধ্যে অস্থিরতার সংজ্ঞা যা প্রকৃতপক্ষে আচরণের অনুকরণ করে, এটি কোনও বহনযোগ্য লেখার জন্য প্রয়োজনীয়ভাবে অসম্ভব করে তোলে " সিকিউরজিরো মেমরি "ফাংশন?

সম্পাদনা করুন: কিছু আকর্ষণীয় পর্যবেক্ষণ।

#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;
}

কলমিবেবে () থেকে সম্ভাব্য লিখনটি .1.১ ব্যতীত সমস্ত জিসিসি সংস্করণ তৈরি করবে the মেমরি বেড়াতে মন্তব্য করা জিসিসি 6.1 স্টোরগুলিও জেনারেট করে তুলবে, যদিও কেবল কলমেমেবে () থেকে সম্ভাব্য লেখার সংমিশ্রণে।

কেউ কেউ ক্যাশে ফ্লাশ করার পরামর্শও দিয়েছেন। মাইক্রোসফ্ট "সিকিউরজিরো মেমোরি" তে ক্যাশে ফ্লাশ করার চেষ্টা করে নাক্যাশে সম্ভবত যাইহোক বেশ দ্রুত অবৈধ হতে চলেছে, সুতরাং এটি সম্ভবত কোনও বড় বিষয় নয়। এছাড়াও, যদি অন্য কোনও প্রোগ্রাম ডেটা অনুসন্ধানের চেষ্টা করে, বা যদি এটি পৃষ্ঠা ফাইলে লিখিত হতে থাকে তবে এটি সর্বদা শূন্য সংস্করণ হতে পারে।

স্ট্যান্ডেলোন ফাংশনে মেমসেট () ব্যবহার করে জিসিসি 6.1 সম্পর্কে কিছু উদ্বেগ রয়েছে। গডবোল্টের জিসিসি 6.১ সংকলকটি একটি ভাঙ্গা বিল্ড হতে পারে, কারণ জিসিসি .1.১ মনে হচ্ছে কিছু লোকের স্ট্যান্ডেলোন ফাংশনটির জন্য একটি সাধারণ লুপ (গডবোল্টে 5.3 এর মতো) উত্পন্ন হয়। (Zwol এর উত্তর সম্পর্কে মন্তব্য পড়ুন।)


4
volatileঅন্যথায় প্রমাণিত না হলে আইএমএইচও ব্যবহার করা একটি বাগ is তবে সম্ভবত একটি বাগ। volatileবিপজ্জনক হিসাবে এতটাই সংজ্ঞায়িত - কেবল এটি ব্যবহার করবেন না।
জেস্পার জুহল

19
@ জেসপারজুহল: না, volatileএই ক্ষেত্রে উপযুক্ত।
ডায়েটারিচ এপ্প

9
@ নাথান অলিভার: এটি কাজ করবে না, কারণ সংকলকরা মৃত স্টোরগুলি ব্যবহার করলেও তা অপ্টিমাইজ করতে পারে memset। সমস্যাটি হ'ল সংকলকরা ঠিক কী memsetজানেন।
ডায়েটারিচ এপ্প

8
@ পলস্টেলিয়ান: এটি একটি volatileপয়েন্টার তৈরি করবে , আমরা একটি পয়েন্টার চাই volatile(আমরা ++কঠোর কিনা তা যত্নশীল নয় , তবে *p = 0কঠোর কিনা )।
ডায়েটারিচ এপ্প

7
@ জেসপারজুহল: অস্থিরতা সম্পর্কিত কোনও নির্দিষ্ট নেই।
GManNickG

উত্তর:


82

জিসিসির আচরণটি সামঞ্জস্যপূর্ণ হতে পারে, এবং তা না হলেও, volatileএই জাতীয় ক্ষেত্রে আপনি যা চান তার উপর নির্ভর করা উচিত নয় । volatileমেমরি-ম্যাপযুক্ত হার্ডওয়্যার নিবন্ধগুলির জন্য এবং অস্বাভাবিক নিয়ন্ত্রণ প্রবাহের সময় পরিবর্তিত পরিবর্তনশীলগুলির জন্য সি সি কমিটি (যেমন সিগন্যাল হ্যান্ডলার এবং setjmp)। এটি কেবলমাত্র এটির জন্য নির্ভরযোগ্য। সাধারণ হিসাবে "এটিকে অপ্টিমাইজ করবেন না" হিসাবে টিকাটি হিসাবে নিরাপদ নয়।

বিশেষত, মানটি মূল পয়েন্টে অস্পষ্ট। (আমি আপনার কোডটি সি তে রূপান্তর করেছি; এখানে সি এবং সি ++ এর মধ্যে কোনও বিভেদ থাকা উচিত নয় I've আমি নিজে নিজেও ইনলাইনিংটি সম্পন্ন করেছি যা প্রশ্নোত্তর অপ্টিমাইজেশনের আগে ঘটবে, কম্পাইলারটি সেই সময়ে "কী দেখছে" তা দেখানোর জন্য ।)

extern void use_arr(void *, size_t);
void foo(void)
{
    char arr[8];
    use_arr(arr, sizeof arr);

    for (volatile char *p = (volatile char *)arr;
         p < (volatile char *)(arr + 8);
         p++)
      *p = 0;
}

মেমরি ক্লিয়ারিং লুপটি arrএকটি অস্থির-যোগ্য লভ্যালুয়ের মাধ্যমে অ্যাক্সেস করে তবে arrনিজেই তা ঘোষিত হয় নাvolatile । লুপের তৈরি স্টোরগুলি "মৃত" এবং লুপ পুরোপুরি মুছে ফেলার জন্য এটি কমপক্ষে সি সংকলকের পক্ষে কমপক্ষে যুক্তিযুক্তভাবে মঞ্জুরিপ্রাপ্ত। সেখানে সি নীতি পাঠ্য যে বোঝা যে কমিটির বোঝানো ঐ দোকান প্রয়োজন সংরক্ষিত করা, কিন্তু মান নিজেই আসলে, যে প্রয়োজন দেখা যায় না যেমন তা পড়তে থাকি।

স্ট্যান্ডার্ডটি কী কী প্রয়োজন বা কী প্রয়োজন না সে সম্পর্কে আরও আলোচনার জন্য দেখুন কেন একটি অস্থির স্থানীয় ভেরিয়েবলটি একটি অস্থির যুক্তি থেকে আলাদাভাবে অনুকূলিত হয় এবং কেন অপ্টিমাইটিয়ারটি পরবর্তীটি থেকে কোনও অপ-লুপ তৈরি করে? , একটি অস্থির রেফারেন্স / পয়েন্টার মাধ্যমে একটি ঘোষিত অ-উদ্বায়ী বস্তু অ্যাক্সেস করা কি অ্যাক্সেসের উপর ভিত্তি করে অস্থির নিয়ম সরবরাহ করে? , এবং জিসিসি বাগ 71793

কি কমিটি সম্পর্কে আরো জানার জন্য চিন্তার volatile ছিল, অনুসন্ধান C99 নীতি শব্দ "উদ্বায়ী" জন্য। জন রেগারের কাগজ " ভোল্টাইলগুলি বিবিধভাবে বিভ্রান্ত করা " বিস্তারিতভাবে চিত্রিত করে যে কীভাবে প্রোগ্রামার প্রত্যাশাগুলি প্রযোজনা সংকলকগুলিরvolatile দ্বারা সন্তুষ্ট হতে পারে না। এলএলভিএম দলের ধারাবাহিক প্রবন্ধগুলি " কি প্রতিটি সি প্রোগ্রামারকে অনির্ধারিত আচরণ সম্পর্কে জেনে রাখা উচিত " নির্দিষ্টভাবে স্পর্শ করে না volatileতবে আধুনিক সি সংকলকগুলি কীভাবে এবং কেন "পোর্টেবল অ্যাসেমব্লারস" নয় তা বুঝতে আপনাকে সহায়তা করবে ।


আপনি যা করতে চেয়েছিলেন এমন কোনও ফাংশন কীভাবে কার্যকর করতে হবে তার ব্যবহারিক প্রশ্নের কাছে volatileZeroMemory: স্ট্যান্ডার্ডটি যা প্রয়োজন তা নির্ধারণ করা বা প্রয়োজনীয়তা নির্বিশেষে, এই ধারণাটি গ্রহণ করা বুদ্ধিমানের হবে যে আপনি এটি ব্যবহার করতে পারবেন না volatile। সেখানে হয় একটি বিকল্প যে কাজ ওপরেই নির্ভরশীল হতে পারে, কারণ এটি পর্যন্ত খুব বেশী অন্যান্য উপাদান ভঙ্গ করেছো এটা কাজ করে নি হবে:

extern void memory_optimization_fence(void *ptr, size_t size);
inline void
explicit_bzero(void *ptr, size_t size)
{
   memset(ptr, 0, size);
   memory_optimization_fence(ptr, size);
}

/* in a separate source file */
void memory_optimization_fence(void *unused1, size_t unused2) {}

তবে আপনাকে অবশ্যই একেবারে নিশ্চিত করতে হবে যে memory_optimization_fenceএটি কোনও পরিস্থিতিতেই অন্তর্ভুক্ত নয়। এটি অবশ্যই তার নিজস্ব উত্স ফাইলে থাকা উচিত এবং এটি অবশ্যই লিঙ্ক-টাইম অপ্টিমাইজেশনের শিকার হওয়া উচিত নয়।

সংকলক এক্সটেনশনের উপর নির্ভর করে অন্যান্য বিকল্প রয়েছে, যা কিছু পরিস্থিতিতে ব্যবহারযোগ্য এবং কঠোর কোড তৈরি করতে পারে (এর মধ্যে একটি উত্তর এই উত্তরটির পূর্ববর্তী সংস্করণে প্রকাশিত হয়েছিল), তবে কোনওটি সর্বজনীন নয়।

(আমি ফাংশনটি কল করার পরামর্শ দিচ্ছি explicit_bzero, কারণ এটি নামের অধীনে এটি একাধিক সি লাইব্রেরিতে পাওয়া যায় the নামটির জন্য কমপক্ষে আরও চার জন প্রতিদ্বন্দ্বী রয়েছেন, তবে প্রত্যেকে কেবল একটি সি লাইব্রেরি গৃহীত হয়েছে))

আপনার এটিও জানা উচিত, এমনকি আপনি যদি এটি কাজ করতে পারেন তবে এটি যথেষ্ট নাও হতে পারে। বিশেষত, বিবেচনা করুন

struct aes_expanded_key { __uint128_t rndk[16]; };

void encrypt(const char *key, const char *iv,
             const char *in, char *out, size_t size)
{
    aes_expanded_key ek;
    expand_key(key, ek);
    encrypt_with_ek(ek, iv, in, out, size);
    explicit_bzero(&ek, sizeof ek);
}

AES ত্বরণের নির্দেশাবলী সহ হার্ডওয়্যার ধরে নেওয়া, যদি expand_keyএবং encrypt_with_ekইনলাইন হয়, সংকলক ekভেক্টর রেজিস্টার ফাইলটিতে পুরোপুরি রাখতে সক্ষম হতে পারে - কল না করা পর্যন্ত explicit_bzero, যা কেবল এটি মুছে ফেলার জন্য স্ট্যাকের মধ্যে সংবেদনশীল ডেটা অনুলিপি করতে বাধ্য করে, এবং, আরও খারাপ, কীগুলি এখনও ভেক্টর রেজিস্টারগুলিতে বসে আছে সেগুলি সম্পর্কে ভয়ঙ্কর কাজ করবেন না!


6
এটি আকর্ষণীয় ... আমি কমিটির মন্তব্যের একটি উল্লেখ দেখতে আগ্রহী হব।
ডায়েটারিচ এপ্প

10
Square.7.৩ ()) এর সংজ্ঞা volatileহিসাবে এই বর্গটি কীভাবে [...] সুতরাং এই জাতীয় কোনও বিষয় উল্লেখ করে যে কোনও অভিব্যক্তিটি 5.1.2.3-এ বর্ণিত বিমূর্ত মেশিনের নিয়ম অনুসারে কঠোরভাবে মূল্যায়ন করা হবে। তদ্ব্যতীত, প্রতিটি ক্রম বিন্দুতে অবজেক্টে সর্বশেষ সঞ্চিত মানটি পূর্বে উল্লিখিত অজানা উপাদানগুলির দ্বারা সংশোধিত ব্যতীত অ্যাবস্ট্রাক্ট মেশিন দ্বারা নির্ধারিত সাথে সম্মত হবে । অস্থির-যোগ্য টাইপযুক্ত কোনও সামগ্রীর অ্যাক্সেসকে কী কার্যকর করে তা বাস্তবায়ন-সংজ্ঞায়িত। ?
Iwillnotexist আইডোনোটেক্সিস্ট

15
@IwillnotexistIdonotexist এই উত্তরণে মূল শব্দটি অবজেক্টvolatile sig_atomic_t flag;একটি উদ্বায়ী বস্তু*(volatile char *)fooকেবলমাত্র একটি অস্থির-যোগ্য লভ্যালুয়ের মাধ্যমে অ্যাক্সেস এবং মানকটির কোনও বিশেষ প্রভাব থাকতে হবে না।
zwol

4
স্ট্যান্ডার্ড বলছে যে কোনও কিছু "মান্যকারী" বাস্তবায়ন হওয়ার জন্য কোন মানদণ্ডের মাপকাঠি করতে হবে। "ভাল" বাস্তবায়ন বা "ব্যবহারযোগ্য" হতে একটি প্রদত্ত প্ল্যাটফর্মের বাস্তবায়নের কী মানদণ্ড অবশ্যই পূরণ করতে হবে তা বর্ণনা করার কোনও প্রচেষ্টা করে না। জিসিসির চিকিত্সা volatileএটি "অনুগত" বাস্তবায়ন করার পক্ষে পর্যাপ্ত হতে পারে তবে এর অর্থ এই নয় যে এটি "ভাল" বা "দরকারী" হওয়ার পক্ষে যথেষ্ট। বিভিন্ন ধরণের সিস্টেমের প্রোগ্রামিংয়ের জন্য এগুলি সম্পর্কিত খারাপভাবে অভাব হিসাবে বিবেচনা করা উচিত।
সুপারক্যাট

4
সি স্পেক আরও সরাসরি বলেছে "সত্যিকারের বাস্তবায়নের কোনও অভিব্যক্তির অংশের মূল্যায়ন করা দরকার না যদি এটির মূল্য নির্ধারণ করা হয় না এবং কোনও প্রয়োজনীয় পার্শ্ব প্রতিক্রিয়া তৈরি হয় না ( কোনও ফাংশন ডেকে বা অস্থির বস্তু অ্যাক্সেস করার কারণে যে কোনও কারণে ) " (আমার উপর জোর দিন)।
জোহানেস স্কাউব -

15

আমার এমন একটি ফাংশন দরকার যা (উইনপিআই থেকে সিকিউরজিরো মেমোরির মতো) সর্বদা স্মৃতিশক্তিটি শূন্য করে এবং অপ্টিমাইজড হয় না,

এটি স্ট্যান্ডার্ড ফাংশনটির memset_sজন্য।


উদ্বায়ী সঙ্গে এই আচরণ বা অনুসারী করতে হবে কিনা তা হিসেবে যে একটু কঠিন বলে, এবং উদ্বায়ী হয়েছে বলেন দীর্ঘ বাগ সঙ্গে জর্জরিত হয়েছে।

একটি বিষয় হ'ল চশমাগুলি বলে যে "বিমূর্ত যন্ত্রের নিয়ম অনুসারে অস্থির বস্তুগুলির প্রবেশের কঠোরভাবে মূল্যায়ন করা হয়।" তবে এটি কেবল 'উদ্বায়ী বস্তু' বোঝায়, অস্থির যুক্ত হওয়া পয়েন্টারের মাধ্যমে কোনও অ-উদ্বায়ী বস্তু অ্যাক্সেস না করে। স্পষ্টতই যদি কোনও সংকলক বলতে পারে যে আপনি সত্যই কোনও উদ্বায়ী বস্তুটি অ্যাক্সেস করছেন না তবে তার পরে অবজেক্টটিকে অস্থির হিসাবে বিবেচনা করার প্রয়োজন নেই।


4
দ্রষ্টব্য: এটি সি 11 স্ট্যান্ডার্ডের অংশ, এবং এখনও সমস্ত সরঞ্জামচেইনে উপলভ্য নয়।
ডায়েটারিচ এপ্প

4
একটি লক্ষ্য করা উচিত যে আকর্ষণীয়ভাবে, এই ফাংশনটি সি 11 এর জন্য মানক করা হয়েছে তবে সি ++ 11, সি ++ 14 বা সি ++ 17 এর জন্য নয়। সুতরাং প্রযুক্তিগতভাবে এটি সি ++ এর সমাধান নয়, তবে আমি সম্মত হই যে এটি ব্যবহারিক দৃষ্টিকোণ থেকে সেরা বিকল্প বলে মনে হচ্ছে। এই মুহুর্তে আমি অবাক হই যদিও জিসিসির আচরণটি মানিয়ে নিচ্ছে কিনা। সম্পাদনা করুন: আসলে, ভিএস 2015 এর মেমসেট_ নেই, তাই এটি এখনও এতগুলি বহনযোগ্য নয়।
কুকি 451

4
@ কুকি 451 আমি ভেবেছিলাম সি ++ 17 রেফারেন্স অনুসারে সি 11 স্ট্যান্ডার্ড লাইব্রেরিটি টানছে (দ্বিতীয় মিস দেখুন)।
nwp

14
এছাড়াও, memset_sসি 11-স্ট্যান্ডার্ড হিসাবে বর্ণনা করা একটি ওভারস্টেটমেন্ট। এটি আনেক্সেক্স কে এর অংশ, যা সি 11 এ alচ্ছিক (এবং তাই সি ++ এও optionচ্ছিক)। মূলত মাইক্রোসফ্ট সহ সমস্ত বাস্তবায়নকারী, যার ধারণা এটি প্রথম স্থানে ছিল (!), তারা এটি গ্রহণ করতে অস্বীকার করেছে; শেষ আমি শুনেছি তারা সি-নেক্সটে এটিকে স্ক্র্যাপ করার বিষয়ে কথা বলছিল।
zwol

8
@ কুকি 451 নির্দিষ্ট চেনাশোনাগুলিতে মাইক্রোসফ্ট মূলত প্রত্যেকের আপত্তির তুলনায় সি স্ট্যান্ডার্ডে স্টাফ চাপিয়ে দেওয়ার জন্য কুখ্যাত এবং তারপরে সেগুলি নিজে প্রয়োগ করতে বিরক্ত করে না। (এই অধিকাংশ গুরুতর উদাহরণ কি অন্তর্নিহিত টাইপ জন্য নিয়ম C99 এর শিথিলকরণ হয় size_tহতে অনুমোদিত হয়। দ্য Win64 ABI- র C90 সঙ্গে conformant নয় নয়। যে হত ... ঠিক আছে , কিন্তু ভয়ানক না ... যদি MSVC আসলে মত C99 জিনিষ আপ বাছাই করা ছিল uintmax_tএবং %zuএকটি সময়োপযোগী ফ্যাশন, কিন্তু তারা না )।
zwol

2

আমি এই সংস্করণটিকে পোর্টেবল সি ++ হিসাবে অফার করি (যদিও শব্দার্থকগুলি সম্পূর্ণ ভিন্ন):

void volatileZeroMemory(volatile void* const ptr, unsigned long long size)
{
    volatile unsigned char* bytePtr = new (ptr) volatile unsigned char[size];

    while (size--)
    {
        *bytePtr++ = 0;
    }
}

এখন আপনার কাছে একটি অস্থির অবজেক্টে লেখার প্রবেশাধিকার রয়েছে , কেবলমাত্র অবজেক্টের অস্থির দৃষ্টিভঙ্গির মাধ্যমে তৈরি কোনও অ-উদ্বায়ী বস্তুতে অ্যাক্সেস নয়।

অর্থগত পার্থক্য হ'ল এটি এখন আনুষ্ঠানিকভাবে যেকোনো বস্তু (গুলি) মেমরি অঞ্চলটি দখল করেছে, কারণ স্মৃতি পুনরায় ব্যবহার করা হয়েছে। সুতরাং বস্তুটির বিষয়বস্তু শূন্য করার পরে অ্যাক্সেস এখন অবশ্যই অপরিজ্ঞাত আচরণ (পূর্বে এটি বেশিরভাগ ক্ষেত্রে অপরিজ্ঞাত আচরণ করা হত, তবে কিছু ব্যতিক্রম অবশ্যই বিদ্যমান ছিল)।

শেষের পরিবর্তে কোনও অবজেক্টের জীবদ্দশায় এই শূন্যকরণটি ব্যবহার করার জন্য, কলারটিকে newমূল টাইপের নতুন উদাহরণটি আবার ফিরিয়ে রাখতে প্লেসমেন্ট ব্যবহার করা উচিত ।

কোডটি সংক্ষিপ্ততর করা যেতে পারে (কম স্বচ্ছ হলেও) মান সূচনা ব্যবহার করে:

void volatileZeroMemory(volatile void* const ptr, unsigned long long size)
{
    new (ptr) volatile unsigned char[size] ();
}

এবং এই মুহুর্তে এটি একটি ওয়ানলাইনার এবং সবেমাত্র কোনও সহায়ক ফাংশনকে সতর্ক করে।


4
যদি ফাংশনটি কার্যকর হওয়ার পরে যদি অবজেক্টে অ্যাক্সেস হয় তবে ইউবি ডেকে আনবে, এর অর্থ এই যে এই ধরণের অ্যাক্সেসগুলি বস্তুটি "ক্লিয়ার" হওয়ার আগে ধারণকৃত মানগুলি অর্জন করতে পারে। এটি কীভাবে সুরক্ষার বিপরীতে নয়?
সুপারক্যাট

0

ডান হাতের দিকে একটি অস্থির অবজেক্ট ব্যবহার করে এবং সংকলককে স্টোরগুলিকে অ্যারে সংরক্ষণ করার জন্য জোর করে ফাংশনের একটি বহনযোগ্য সংস্করণ লেখা সম্ভব should

void volatileZeroMemory(void* ptr, unsigned long long size)
{
    volatile unsigned char zero = 0;
    unsigned char* bytePtr = static_cast<unsigned char*>(ptr);

    while (size--)
    {
        *bytePtr++ = zero;
    }

    zero = static_cast<unsigned char*>(ptr)[zero];
}

zeroবস্তুর ঘোষিত হয় volatileনিশ্চিত যে কম্পাইলার যদিও এটা সবসময় শূন্য হিসাবে মূল্যায়ন এর মান সম্পর্কে কোন অনুমানের করতে পারেন।

চূড়ান্ত অ্যাসাইনমেন্ট এক্সপ্রেশন অ্যারেতে একটি উদ্বায়ী সূচক থেকে পড়ে এবং একটি উদ্বায়ী বস্তুতে মানটি সঞ্চয় করে। যেহেতু এই পঠনটি অপ্টিমাইজ করা যায় না, এটি নিশ্চিত করে যে সংকলক অবশ্যই লুপে উল্লিখিত স্টোরগুলি উত্পন্ন করবে।


4
এটি মোটেই কাজ করে না ... কেবল উত্পন্ন করা কোডটি দেখুন।
কুকি 451

4
আমার উত্পন্ন এএসএম মো 'আরও ভাল করে পড়ার পরে, এটি ফাংশন কলটি ইনলাইন করে এবং লুপিং বজায় রাখবে বলে মনে হচ্ছে, তবে *ptrসেই লুপের সময় কোনও স্টোরিং করবেন না বা আসলে কিছু নেই ... কেবল লুপিং। ডাব্লুটিএফ, আমার মস্তিষ্ক আছে।
আন্ডারস্কোর_১

4
@ আসরস্কোর_ডি কারণ এটি উদ্বোধনের পড়ার সংরক্ষণের সময় দোকানটিকে অপ্টিমাইজ করে।
ডি ক্রুয়েগার

4
হ্যাঁ, এবং এটি ফলাফলটিকে অপরিবর্তিত রাখে edx: আমি এটি পেয়েছি:.L16: subq $1, %rax; movzbl -1(%rsp), %edx; jne .L16
আন্ডারস্কোর_ড

4
যদি আমি একটি স্বেচ্ছাসেবী volatile unsigned char constফিল বাইট পাস করার অনুমতি দেওয়ার জন্য যদি ফাংশনটি পরিবর্তন করি ... তবে এটি এটি পড়ে না । উত্পন্ন ইনলাইনড কলটি volatileFill()ঠিক [load RAX with sizeof] .L9: subq $1, %rax; jne .L9। কেন অপ্টিমাইজার (এ) পূরণ করুন বাইটটি পুনরায় পড়বেন না এবং (খ) লুপটি যেখানে কিছু করেন না তা সংরক্ষণে বিরক্ত করছেন?
আন্ডারস্কোর_১
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.