সিতে স্ট্রাক প্যাকিংয়ের জন্য কি কোনও স্ট্যান্ডার্ড উপায় বা মানক বিকল্প রয়েছে?


13

যখন সিআই-তে প্রোগ্রামিং জিসিসি __attribute__((__packed__))বৈশিষ্ট্যটি ব্যবহার করে স্ট্রাকগুলি প্যাক করা অমূল্য বলে মনে করে থাকে তাই আমি সহজেই অস্থির মেমরির একটি কাঠামোগত অংশকে বাসের মাধ্যমে সঞ্চারিত বা স্টোরেজে সংরক্ষণের জন্য বা রেজিস্টারগুলির একটি ব্লকে প্রয়োগ করার জন্য বাইটের একটি অ্যারে রূপান্তর করতে পারি। প্যাকযুক্ত স্ট্রাক্টস গ্যারান্টি দেয় যে বাইটের অ্যারে হিসাবে বিবেচনা করা হলে এতে কোনও প্যাডিং থাকবে না, যা উভয়ই অপব্যয়যোগ্য, সম্ভাব্য সুরক্ষার ঝুঁকি এবং সম্ভবত হার্ডওয়্যারকে ইন্টারফেস করার সময় বেমানান।

সমস্ত সি সংকলকগুলিতে কাজ করে এমন স্ট্রিংগুলির প্যাকিংয়ের কোনও মান নেই? যদি না হয় তবে আমি ভাবতে একজন আউটরিয়ার এটি সিস্টেম প্রোগ্রামিংয়ের জন্য একটি গুরুত্বপূর্ণ বৈশিষ্ট্য? সি ভাষার প্রাথমিক ব্যবহারকারীরা কি প্যাকিং স্ট্রাকগুলির প্রয়োজনীয়তা খুঁজে পাননি বা কোনও ধরণের বিকল্প আছে?


কম্পাইল ডোমেন জুড়ে স্ট্রোক ব্যবহার করা খুব খারাপ ধারণা, বিশেষত হার্ডওয়ারকে নির্দেশ করা (যা অন্য একটি কম্পাইল ডোমেন)। প্যাকেট স্ট্রোকগুলি এটি করার জন্য কেবল একটি কৌশল, তাদের প্রচুর খারাপ পার্শ্ব প্রতিক্রিয়া রয়েছে, তাই আপনার পার্শ্ব প্রতিক্রিয়াযুক্ত আরও অনেক সমস্যার সমাধান রয়েছে এবং এগুলি আরও বহনযোগ্য।
old_timer

উত্তর:


12

স্ট্রাক্টে, কী গুরুত্বপূর্ণ তা হ'ল প্রতিটি কাঠামোর উদাহরণ থেকে প্রতিটি সদস্যের অফসেট। জিনিসগুলি কীভাবে শক্তভাবে বস্তাবন্দী হয় তা এতটা নয়।

একটি অ্যারে যাইহোক, এটি কীভাবে "প্যাকড" তা বিবেচনা করে। সি-র নিয়মটি হ'ল প্রতিটি অ্যারে উপাদান হ'ল আগের থেকে এন বাইট, যেখানে এন সেই ধরণের সঞ্চয় করতে ব্যবহৃত বাইটের সংখ্যা।

তবে স্ট্রাক্ট সহ, অভিন্নতার জন্য এমন কোনও প্রয়োজন নেই।

একটি অদ্ভুত প্যাকিং স্কিমের একটি উদাহরণ এখানে:

ফ্রিস্কেল (যারা স্বয়ংচালিত মাইক্রোকন্ট্রোলার তৈরি করেন) এমন একটি মাইক্রো তৈরি করেন যা টাইম প্রসেসিং ইউনিট সহ-প্রসেসর (ইটিপিইউ বা টিপিইউ এর জন্য গুগল) রাখে। এর দুটি নেটিভ ডেটা মাপ, 8 বিট এবং 24 বিট রয়েছে এবং কেবল পূর্ণসংখ্যার সাথে কাজ করে।

এই কাঠামো:

struct a
{
  U24 elementA;
  U24 elementB;
};

প্রতিটি ইউ 24 তার নিজস্ব 32 বিট ব্লক সঞ্চিত দেখতে পাবে, তবে কেবলমাত্র সর্বোচ্চ ঠিকানা অঞ্চলে।

এই:

struct b
{
  U24 elementA;
  U24 elementB;
  U8  elementC;
};

সংলগ্ন 32 বিট ব্লকগুলিতে দুটি U24 গুলি সঞ্চিত থাকবে এবং U8 প্রথম U24 এর আগে "গর্ত" এ সংরক্ষণ করা হবে elementA

আপনি যদি চান তবে আপনি কম্পাইলারটিকে সবকিছু 32 টি বিট ব্লকের মধ্যে প্যাক করতে বলতে পারেন; এটি র‍্যামে আরও ব্যয়বহুল তবে অ্যাক্সেসের জন্য কম নির্দেশাবলী ব্যবহার করে।

"প্যাকিং" এর অর্থ "শক্ত করে প্যাক করা" নয় - এর অর্থ অফসেটের স্ট্রাক্টের উপাদানগুলি সাজানোর জন্য কিছু পরিকল্পনা।

কোনও জেনেরিক স্কিম নেই, এটি সংকলক + আর্কিটেকচার নির্ভর।


1
যদি টিপিইউর জন্য সংকলকটি অন্য উপাদানগুলির struct bকোনওর elementCআগে সরে যেতে পুনরায় সজ্জিত করে, তবে এটি কনফার্মিং সি সংকলক নয়। সি
বার্ট ভ্যান ইনজেন শেহানাউ 13'16

আকর্ষণীয় তবে U24 স্ট্যান্ডার্ড সি টাইপ নয় en.m.wikedia.org/wiki/C_data_types তাই অবাক হওয়ার কিছু নেই যে কমপ্লায়ার এটিকে কিছুটা বিজোড়ভাবে পরিচালনা করতে বাধ্য হয়।
satur9nine

এটি মূল সিপিইউ কোরের সাথে র‌্যাম ভাগ করে যা শব্দটির আকার 32 বিট। তবে এই প্রসেসরের একটি ALU রয়েছে যা কেবল 24 বিট বা 8 বিট নিয়ে কাজ করে। সুতরাং এটিতে 32 বিট শব্দের মধ্যে 24 বিট সংখ্যা রাখার জন্য একটি পরিকল্পনা রয়েছে। মানহীন, তবে প্যাকিং এবং প্রান্তিককরণের দুর্দান্ত উদাহরণ। সম্মত, এটি খুব অ-মানক।
রিচকালর্স

6

সিআই-তে প্রোগ্রামিং যখন জিসিসি ব্যবহার করে স্ট্রাক প্যাক করা অমূল্য বলে মনে করে __attribute__((__packed__))[...]

যেহেতু আপনি উল্লেখ করেছেন __attribute__((__packed__)), আমি ধরে নিলাম আপনার উদ্দেশ্য হ'ল একটি এর মধ্যে সমস্ত প্যাডিং অপসারণ করা struct(প্রতিটি সদস্যকে 1 বাইট সারিবদ্ধকরণ করুন)।

সমস্ত সি সংকলকগুলিতে কাজ করে এমন স্ট্রিংগুলির প্যাকিংয়ের কোনও মান নেই?

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

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

কোনও বাহ্যিক উত্সে এই জাতীয় ডেটা আউটপুট দেওয়ার সবচেয়ে নিরাপদ এবং সর্বাধিক পোর্টেবল উপায় হ'ল আপনার কাঁচা মেমরির সামগ্রীগুলি প্রেরণের চেষ্টা করার পরিবর্তে বাইট স্ট্রিমগুলিতে / থেকে ক্রমিক করা structs। এটি আপনার প্রোগ্রামটিকে এই সিরিয়ালাইজেশন প্রসঙ্গে বাইরে পারফরম্যান্সের জরিমানার হাত থেকে structবাঁচায় এবং পুরো সফ্টওয়্যারটি ছুঁড়ে ফেলে এবং গ্লাইচ না করে অবাধে নতুন ক্ষেত্র যুক্ত করতে দেয় । এটি কখনই উদ্বেগের বিষয় হয়ে দাঁড়ায় যদি শেষের দিক এবং এই জাতীয় জিনিসগুলি মোকাবেলার জন্য আপনাকে কিছু জায়গা দেয়।

সংকলক-নির্দিষ্ট নির্দেশাবলীর কাছে না পৌঁছে সমস্ত প্যাডিং অপসারণের একটি উপায় রয়েছে, যদিও ক্ষেত্রগুলির মধ্যে আপেক্ষিক ক্রমটি বিবেচনা না করে তবে এটি কেবলমাত্র প্রযোজ্য। এরকম কিছু দেওয়া হয়েছে:

struct Foo
{
    double x;  // assume 8-byte alignment
    char y;    // assume 1-byte alignment
               // 7 bytes of padding for first field
};

... আমাদের এই ক্ষেত্রগুলি সমন্বিত কাঠামোর ঠিকানার সাথে সম্পর্কিত সারিবদ্ধ মেমরি অ্যাক্সেসের জন্য প্যাডিং প্রয়োজন:

0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
x_______y.......x_______y.......x_______y.......x_______y.......

... যেখানে .প্যাডিং নির্দেশ করে। xপারফরম্যান্সের জন্য প্রত্যেককে অবশ্যই 8-বাইট সীমানায় সারিবদ্ধ হতে হবে (এবং কখনও কখনও এমনকি সঠিক আচরণও)।

আপনি যেমন একটি SoA (অ্যারের কাঠামো) উপস্থাপনা ব্যবহার করে একটি পোর্টেবল উপায়ে প্যাডিং অপসারণ করতে পারেন (আসুন ধরে নেওয়া যাক আমাদের 8 টি Fooদৃষ্টান্ত প্রয়োজন ):

struct Foos
{
   double x[8];
   char y[8];
};

আমরা কার্যকরভাবে কাঠামোটি ভেঙে ফেলেছি। এই ক্ষেত্রে, মেমরির উপস্থাপনাটি এমন হয়:

0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
x_______x_______x_______x_______x_______x_______x_______x_______

... এবং এই:

01234567
yyyyyyyy

... আর কোনও প্যাডিং ওভারহেড নয়, এবং ভুল মিসাইনযুক্ত মেমরি অ্যাক্সেসকে জড়িত না করে যেহেতু আমরা আর কোনও ডেটা ক্ষেত্রের কোনও কাঠামোর ঠিকানার অফসেট হিসাবে অ্যাক্সেস করব না, পরিবর্তে কার্যকরভাবে অ্যারের জন্য একটি বেস ঠিকানার অফসেট হিসাবে।

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

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


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

হ্যাঁ, যদি আমরা বিটস এবং উপস্থাপনা, প্রান্তিককরণের প্রয়োজনীয়তা, অন্তর্নির্মিতা ইত্যাদির মধ্যে সবকিছু নির্দিষ্ট করে নির্দিষ্ট করতে পারি এবং এমন একটি বৈশিষ্ট্য রয়েছে যা অন্তর্নিহিত আর্কিটেকচার থেকে optionচ্ছিকভাবে আরও তালাক দেওয়ার সময় সিতে এ জাতীয় সুস্পষ্ট নিয়ন্ত্রণের অনুমতি দেয় ... তবে আমি কেবল এই বিষয়েই কথা বলছিলাম এটিএম - বর্তমানে সিরিয়ালাইজারের সর্বাধিক বহনযোগ্য সমাধান হ'ল এটি এমনভাবে লেখা যাতে এটি সঠিক বিট এবং বাইটের উপস্থাপনা এবং ডেটা ধরণের প্রান্তিককরণের উপর নির্ভর করে না। দুর্ভাগ্যক্রমে অন্যথায় কার্যকরভাবে (সি তে) করার আমাদের উপায়ের অভাব রয়েছে।

5

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

যদিও সাধারণ, বাইনারি ডেটা প্রেরণ করতে প্যাক ব্যবহার করা একটি খারাপ ধারণা, যদি আপনি ডেটাটির সুরক্ষা, বহনযোগ্যতা বা দীর্ঘায়ু চান। আপনি আপনার প্রোগ্রামে কোনও উত্স থেকে বাইনারি ব্লবটি প্রায়শই পড়েন। আপনি কতবার সমস্ত মানগুলি বুদ্ধিমানভাবে পরীক্ষা করে দেখেন যে কোনও হ্যাকার বা প্রোগ্রাম পরিবর্তন ডেটাতে 'পেয়েছে না'? আপনি একটি চেক রুটিন কোড করার সময়, আপনি পাশাপাশি আমদানি ও রফতানি রুটিন ব্যবহার করতে পারেন।


0

একটি খুব সাধারণ বিকল্প হ'ল "নাম প্যাডিং":

struct s {
  short s1;
  char  c2;
  char  reserved; // Padding
};

এই করে অনুমান গঠন 8 বাইট padded করা হবে না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.