সীমা ছাড়িয়ে একটি অ্যারে অ্যাক্সেস কোনও ত্রুটি দেয় না, কেন?


177

আমি এই জাতীয় সীমা ছাড়িয়ে একটি সি ++ প্রোগ্রামে মান নির্ধারণ করছি:

#include <iostream>
using namespace std;
int main()
{
    int array[2];
    array[0] = 1;
    array[1] = 2;
    array[3] = 3;
    array[4] = 4;
    cout << array[3] << endl;
    cout << array[4] << endl;
    return 0;
}

প্রোগ্রাম প্রিন্ট 3এবং 4। এটা সম্ভব হবে না। আমি g ++ 4.3.3 ব্যবহার করছি

এখানে কমপাইল এবং রান কমান্ড রয়েছে

$ g++ -W -Wall errorRange.cpp -o errorRange
$ ./errorRange
3
4

কেবলমাত্র অ্যাসাইন করার সময় array[3000]=3000এটি আমাকে আলাদা করার ত্রুটি দেয়।

জিসিসি যদি অ্যারে সীমা পরীক্ষা করে না, তবে আমি কীভাবে নিশ্চিত হতে পারি যে আমার প্রোগ্রামটি সঠিক কিনা, কারণ এটি পরে কিছু গুরুতর সমস্যার কারণ হতে পারে?

আমি উপরের কোডটি প্রতিস্থাপন করেছি

vector<int> vint(2);
vint[0] = 0;
vint[1] = 1;
vint[2] = 2;
vint[5] = 5;
cout << vint[2] << endl;
cout << vint[5] << endl;

এবং এটিও কোনও ত্রুটি তৈরি করে না।


3
সংশ্লিষ্ট প্রশ্ন: stackoverflow.com/questions/671703/...
TSomKes

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

4
কাঁচা অ্যারে দিয়ে স্ক্রু না দিয়ে আপনি নিশ্চিত হতে পারেন যে আপনার প্রোগ্রামটি সঠিক। এম + এমএসড / ওএস প্রোগ্রামিং বাদে সি ++ প্রোগ্রামারদের পরিবর্তে ধারক ক্লাস ব্যবহার করা উচিত। ব্যবহারকারীর ধারকগুলির কারণে এটি পড়ুন। parashift.com/c++-faq-lite/containers.html
জকি

8
মনে রাখবেন যে ভেক্টরগুলি [] ব্যবহার করে অগত্যা পরিসীমা-চেক করে না। .At () ব্যবহার করা []] এর মতো একই কাজ করে তবে পরিসীমা-চেক করে।
ডেভিড থর্নলি

4
সীমার বাইরে থাকা উপাদানগুলিতে অ্যাক্সেস করার সময় একটি স্বয়ংক্রিয় আকার পরিবর্তন vector করে না ! এটা শুধু ইউবি!
পাভেল মিনায়েভ

উত্তর:


364

প্রতিটি সি / সি ++ প্রোগ্রামারের সেরা বন্ধু: অনির্ধারিত আচরণে আপনাকে স্বাগতম

বিভিন্ন কারণে বিভিন্ন কারণে ভাষার মান দ্বারা নির্দিষ্ট করা হয়নি। এই হল তাদের একজন।

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

এটি এমনকি, যদি আপনি সত্যিই হতভাগ্য হয়, হতে পারে প্রদর্শিত সঠিকভাবে কাজ করার।

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

হিসাবে কেন নেই কোনো সীমার মধ্যে রাখার পরীক্ষণ, সেখানে উত্তর একটি দম্পতি দিক আছে:

  • একটি অ্যারে সি থেকে একটি বাকী অংশ রয়েছে সি সি অ্যারেগুলি যতটা আদিম আপনি পেতে পারেন are সামঞ্জস্যপূর্ণ ঠিকানা সহ উপাদানগুলির একটি ক্রম। কোনও সীমাবদ্ধতা যাচাই করা হচ্ছে না কারণ এটি কেবল কাঁচা স্মৃতি প্রকাশ করে। একটি দৃust় সীমানা-চেকিং প্রক্রিয়া বাস্তবায়ন সি তে প্রায় অসম্ভব হত would
  • সি ++ এ, শ্রেণির ধরণের ক্ষেত্রে সীমা পরীক্ষা করা সম্ভব। তবে একটি অ্যারে এখনও সরল পুরানো সি-সামঞ্জস্যপূর্ণ। এটি কোনও শ্রেণি নয়। তদ্ব্যতীত, সি ++ আরও একটি নিয়মে নির্মিত যা বাউন্ডস-চেকিংকে আদর্শ নয়। সি ++ গাইডিং নীতিটি "আপনি যা ব্যবহার করেন না তার জন্য অর্থ প্রদান করেন না" " যদি আপনার কোডটি সঠিক হয় তবে আপনার বাউন্ডস-চেকিংয়ের দরকার নেই এবং রানটাইম বাউন্ডস-চেকিংয়ের ওভারহেডের জন্য আপনাকে বাধ্য করা উচিত নয় should
  • সুতরাং সি ++ std::vectorক্লাস টেম্পলেট সরবরাহ করে, যা উভয়কেই অনুমতি দেয়। operator[]দক্ষ হতে ডিজাইন করা হয়েছে। ভাষার মানটির প্রয়োজন হয় না যে এটি সীমাবদ্ধ পরীক্ষা করা (যদিও এটি এটি নিষিদ্ধ করে না)। একটি ভেক্টরের at()সদস্য ফাংশনও রয়েছে যা গণ্ডি-চেকিংয়ের গ্যারান্টিযুক্ত । সুতরাং সি ++ এ আপনি যদি কোনও ভেক্টর ব্যবহার করেন তবে উভয় বিশ্বের সেরা পাবেন। আপনি বাউন্ডস-চেকিং ছাড়াই অ্যারের মতো পারফরম্যান্স পাবেন এবং আপনি যখন চাইবেন তখন সীমা-চেক অ্যাক্সেস ব্যবহার করার ক্ষমতা পাবেন the

5
@ জাইফ: আমরা এতদিন ধরে এই অ্যারে জিনিসটি ব্যবহার করে আসছি তবে এখনও এত সাধারণ ত্রুটি পরীক্ষা করার জন্য কেন পরীক্ষা করা হচ্ছে না?
seg.server.fault

7
সি ++ ডিজাইনের নীতিটি হ'ল এটি সমতুল্য সি কোডের চেয়ে ধীর হওয়া উচিত নয় এবং সি অ্যারে বাউন্ড চেকিং করে না। সি ডিজাইনের নীতিটি মূলত গতি ছিল কারণ এটি সিস্টেম প্রোগ্রামিংয়ের উদ্দেশ্যে ছিল। অ্যারে বাউন্ড চেক করতে সময় লাগে, এবং এটি করা হয় না। সি ++ এর বেশিরভাগ ব্যবহারের জন্য, আপনার যেকোন উপায়ে অ্যারের পরিবর্তে একটি ধারক ব্যবহার করা উচিত এবং যথাক্রমে .at () বা [] এর মাধ্যমে কোনও উপাদান অ্যাক্সেস করে আপনার পছন্দ বাউন্ড চেক বা আপনার কোনও বাউন্ড চেক থাকতে পারে।
কেটিসি

4
@seg এই ধরনের চেকটির জন্য কিছু খরচ হয়। আপনি যদি সঠিক কোডটি লিখেন তবে আপনি সেই মূল্যটি দিতে চান না। এটি বলার পরে, আমি std :: ভেক্টর এ () পদ্ধতিতে একটি সম্পূর্ণ রূপান্তরিত হয়েছি, যা পরীক্ষা করা হয়েছে। এটি ব্যবহার করে আমি "সঠিক" কোড বলে ভেবেছিলাম তাতে বেশ কয়েকটি ত্রুটি ফুটে উঠেছে।

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

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

31

ছ ব্যবহার ++ আপনি কমান্ড লাইন বিকল্প যোগ করতে পারেন: -fstack-protector-all

আপনার উদাহরণে এটি নিম্নলিখিত ফলাফল:

> g++ -o t -fstack-protector-all t.cc
> ./t
3
4
/bin/bash: line 1: 15450 Segmentation fault      ./t

এটি আপনাকে সমস্যাটি সমাধান করতে বা সমাধান করতে সত্যিই সহায়তা করে না, তবে কমপক্ষে সেগফল্ট আপনাকে জানায় যে কিছু ভুল।


10
আমি সবেমাত্র একটি আরও ভাল বিকল্প পেয়েছি: -ফ্মুদফ্ল্যাপ
হাই-অ্যাঞ্জেল

1
@ হাই-অ্যাঞ্জেল: আধুনিক সমতুল্য -fsanitize=addressযা এই বাগটি সংকলনের সময় (যদি অনুকূলিত করা হয়) এবং রানটাইম উভয় সময়েই ধরে।
নাট এল্ডারেজ

@ নেটএলড্রেজ +১, আজকাল আমি এমনকি ব্যবহার করি -fsanitize=undefined,address। তবে এটি লক্ষণীয় যে , স্ট্যান্ডার্ড লাইব্রেরিতে বিরল কোণার কেস রয়েছে, যখন স্যানিটাইজার দ্বারা সীমা ছাড়িয়ে অ্যাক্সেস সনাক্ত করা যায় না । এই কারণে আমি অতিরিক্ত -D_GLIBCXX_DEBUGবিকল্প ব্যবহার করার পরামর্শ দেব , যা আরও বেশি চেক যুক্ত করে।
হাই-অ্যাঞ্জেল

12

g ++ অ্যারের সীমানা যাচাই করে না এবং আপনি ৩,৪ দিয়ে কোনও কিছু ওভাররাইট করতে পারেন তবে সত্যিই গুরুত্বপূর্ণ কিছু নয়, আপনি যদি উচ্চতর সংখ্যার সাথে চেষ্টা করেন তবে আপনি ক্র্যাশ পাবেন।

আপনি স্ট্যাকের যে অংশগুলি ব্যবহার করছেন না সেগুলি কেবল ওভাররাইটিং করছেন, আপনি স্ট্যাকের জন্য বরাদ্দ স্থানের শেষে পৌঁছা অবধি অবিরত রাখতে পারতেন এবং অবশেষে এটি ক্র্যাশ হয়ে যাবে

সম্পাদনা: আপনার সাথে এটির কোনও উপায় নেই, সম্ভবত কোনও স্ট্যাটিক কোড বিশ্লেষক সেই ব্যর্থতাগুলি প্রকাশ করতে পারে, তবে এটি খুব সহজ, আপনার স্ট্যাটিক বিশ্লেষকদের জন্যও একই রকম (তবে আরও জটিল) ব্যর্থতা সনাক্ত করা যেতে পারে maybe


6
অ্যারে [3] এবং অ্যারের ঠিকানার ঠিকানা থেকে যদি আপনি কোথায় পাবেন তবে "সত্যিকারের গুরুত্বপূর্ণ কিছু" নেই ??
নেমজারো

7

আমি যতদূর জানি এটি অপরিজ্ঞাত আচরণ। এটি দিয়ে একটি বৃহত্তর প্রোগ্রাম চালান এবং এটি পথে কোথাও ক্রাশ হবে। বাউন্ড চেকিং কাঁচা অ্যারের অংশ নয় (বা এমনকি স্ট্যান্ড :: ভেক্টর)।

std::vector::iteratorপরিবর্তে এর সাথে স্ট্যান্ড :: ভেক্টর ব্যবহার করুন যাতে আপনার এটি নিয়ে চিন্তা করতে হবে না।

সম্পাদনা:

কেবল মজাদার জন্য, এটি চালান এবং আপনার ক্রাশ হওয়া অবধি কতক্ষণ দেখুন:

int main()
{
   int array[1];

   for (int i = 0; i != 100000; i++)
   {
       array[i] = i;
   }

   return 0; //will be lucky to ever reach this
}

Edit2:

চালাও না।

Edit3:

ঠিক আছে, অ্যারে এবং পয়েন্টারগুলির সাথে তাদের সম্পর্কের বিষয়ে একটি দ্রুত পাঠ এখানে:

আপনি যখন অ্যারে সূচক ব্যবহার করেন, আপনি সত্যই ছদ্মবেশে একটি পয়েন্টার ব্যবহার করছেন ("রেফারেন্স" নামে পরিচিত), এটি স্বয়ংক্রিয়ভাবে অবহেলিত। এই কারণেই * (অ্যারে [1]) এর পরিবর্তে অ্যারে [1] স্বয়ংক্রিয়ভাবে সেই মানটিতে ফিরে আসে।

আপনার যখন কোনও অ্যারেতে পয়েন্টার থাকে, তখন:

int array[5];
int *ptr = array;

তারপরে দ্বিতীয় ঘোষণায় "অ্যারে" সত্যিই প্রথম অ্যারের পয়েন্টারের কাছে ক্ষয় হচ্ছে। এটি এর সমতুল্য আচরণ:

int *ptr = &array[0];

আপনি যখন বরাদ্দ করেছেন তার বাইরে অ্যাক্সেস করার চেষ্টা করার সময়, আপনি সত্যিই কেবল অন্য মেমরির জন্য পয়েন্টার ব্যবহার করছেন (যা সি ++ অভিযোগ করবে না)। আমার উদাহরণস্বরূপ প্রোগ্রামটি গ্রহণ করা, এটি এর সমতুল্য:

int main()
{
   int array[1];
   int *ptr = array;

   for (int i = 0; i != 100000; i++, ptr++)
   {
       *ptr++ = i;
   }

   return 0; //will be lucky to ever reach this
}

সংকলকটি অভিযোগ করবে না কারণ প্রোগ্রামিংয়ে আপনাকে প্রায়শই অন্যান্য প্রোগ্রামগুলি, বিশেষত অপারেটিং সিস্টেমের সাথে যোগাযোগ করতে হয়। এটি বেশ কিছুটা পয়েন্টার দিয়ে করা হয়।


3
আমি মনে করি আপনি সেখানে আপনার শেষ উদাহরণে "পিটিআর" বৃদ্ধি করতে ভুলে গেছেন। আপনি দুর্ঘটনাক্রমে কিছু ভাল সংজ্ঞাযুক্ত কোড তৈরি করেছেন।
জেফ লেক

1
হাহাহা, দেখুন কেন আপনি কাঁচা অ্যারে ব্যবহার করবেন না?
জেকি 16

"এই কারণেই * (অ্যারে [1]) এর পরিবর্তে অ্যারে [1] স্বয়ংক্রিয়ভাবে সেই মানটিতে ফিরে আসে" " আপনি কি নিশ্চিত যে * (অ্যারে [1]) সঠিকভাবে কাজ করবে? আমি মনে করি এটি * হওয়া উচিত (অ্যারে + 1)। PS: লোল, এটি অতীতে কোনও বার্তা প্রেরণের মতো। তবে, যাইহোক:
মুইউস্তান

5

ইঙ্গিত

আপনি যদি পরিসীমা ত্রুটি চেক সহ দ্রুত বাধা আকারের অ্যারেগুলি রাখতে চান তবে বুস্ট :: অ্যারে ব্যবহার করে চেষ্টা করুন ( এটি থেকে স্ট্যান্ডার্ড :: ট্র 1 :: এ্যারে<tr1/array> পরবর্তী সি ++ স্পেসিফিকেশনে স্ট্যান্ডার্ড ধারক হবে)। এটি স্ট্যান্ড :: ভেক্টর এর চেয়ে অনেক দ্রুত। এটি মেমরি সংরক্ষিত করে হিপ বা শ্রেণীর উদাহরণের অভ্যন্তরে যেমন ইনট অ্যারে []।
এটি সাধারণ নমুনা কোড:

#include <iostream>
#include <boost/array.hpp>
int main()
{
    boost::array<int,2> array;
    array.at(0) = 1; // checking index is inside range
    array[1] = 2;    // no error check, as fast as int array[2];
    try
    {
       // index is inside range
       std::cout << "array.at(0) = " << array.at(0) << std::endl;

       // index is outside range, throwing exception
       std::cout << "array.at(2) = " << array.at(2) << std::endl; 

       // never comes here
       std::cout << "array.at(1) = " << array.at(1) << std::endl;  
    }
    catch(const std::out_of_range& r)
    {
        std::cout << "Something goes wrong: " << r.what() << std::endl;
    }
    return 0;
}

এই প্রোগ্রামটি মুদ্রণ করবে:

array.at(0) = 1
Something goes wrong: array<>: index out of range

4

সি বা সি ++ অ্যারে অ্যাক্সেসের সীমা পরীক্ষা করবে না।

আপনি স্ট্যাকের অ্যারে বরাদ্দ করছেন। অ্যারের মাধ্যমে সূচীকরণ array[3]* * এর সমান (array + 3), যেখানে অ্যারে & অ্যারে [0] এর পয়েন্টার হয়। এর ফলে অপরিবর্তিত আচরণ হবে।

কখনও কখনও সি-তে এটি ধরার একটি উপায় হ'ল স্প্লিন্টের মতো একটি স্ট্যাটিক চেকার ব্যবহার করা । আপনি যদি চালান:

splint +bounds array.c

চালু,

int main(void)
{
    int array[1];

    array[1] = 1;

    return 0;
}

তাহলে আপনি সতর্কতা পাবেন:

array.c: (ফাংশন মূলত) অ্যারে.c: 5: 9: সম্ভবত সীমার বাইরে স্টোর: অ্যারে [1] সীমাবদ্ধতা সমাধান করতে অক্ষম: শর্ত পূরণ করতে 0> = 1 প্রয়োজন: ম্যাক্সেট (অ্যারে @ অ্যারে প্রয়োজন) .c: 5: 9)> = 1 একটি মেমরির লিখিত বরাদ্দ বাফারের বাইরে কোনও ঠিকানায় লিখতে পারে।


সংশোধন: এটি ইতিমধ্যে ওএস বা অন্য কোনও প্রোগ্রাম বরাদ্দ করেছে। তিনি অন্য স্মৃতি ওভাররাইট করছেন।
জেকি 16

1
"সি / সি ++ সীমানা যাচাই করবে না" বলা সম্পূর্ণরূপে সঠিক নয় - এটি কোনও ডিফল্টরূপে বা কোনও সংকলনের পতাকা সহ কোনও নির্দিষ্ট অনুগত বাস্তবায়ন করা থেকে বিরত থাকে না। এটা ঠিক যে তাদের কেউ মাথা ঘামায় না।
পাভেল মিনায়েভ

3

আপনি অবশ্যই আপনার স্ট্যাকটি ওভাররাইট করছেন, তবে প্রোগ্রামটি এত সহজ যে এর প্রভাবগুলি লক্ষ্য করা যায় না।


2
স্ট্যাকটি ওভাররাইট করা আছে কি না প্ল্যাটফর্মের উপর নির্ভর করে।
ক্রিস কিল্যান্ড 16

3

ভালগ্রাইন্ডের মাধ্যমে এটি চালান এবং আপনি একটি ত্রুটি দেখতে পাবেন।

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

g++ --stack-check -W -Wall errorRange.cpp -o errorRange
valgrind ./errorRange

valgrind একটি ত্রুটি রিপোর্ট করবে


2
প্রকৃতপক্ষে, ভালগ্র্যান্ড স্ট্যাকের মধ্যে ভুল অ্যারে অ্যাক্সেসগুলি নির্ধারণ করতে যথেষ্ট দুর্বল। (এবং যথাযথভাবে তাই, এটি সর্বোত্তমভাবে করতে পারেন পুরো স্ট্যাকটিকে বৈধ লেখার স্থান হিসাবে চিহ্নিত করুন)
ফালাইনা

@ ফ্যালাইনা - ভাল পয়েন্ট, তবে ভালগ্র্যান্ড কমপক্ষে কিছু স্ট্যাক ত্রুটি সনাক্ত করতে পারে।
টড স্টাউট

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

2

আপনার পক্ষে কাজ করা অপরিজ্ঞাত আচরণ। আপনি ক্লোবার্বিংয়ের যে স্মৃতিতে সম্ভবত দৃশ্যমান তা গুরুত্বপূর্ণ কিছু ধারণ করে না holding নোট করুন যে সি এবং সি ++ অ্যারেগুলিতে সীমাবদ্ধতা পরীক্ষা করে না, সুতরাং এর মতো স্টাফগুলি সংকলন বা রান টাইমে ধরা পড়বে না।


5
না, অপরিজ্ঞাত আচরণটি যখন পরিষ্কারভাবে ক্র্যাশ হয় তখন "আপনার পক্ষে কাজ করে"। যখন এটি কাজ করে প্রদর্শিত হয়, তখন এটি সবচেয়ে খারাপ পরিস্থিতি সম্পর্কে ।
jalf

@ জন বোড: তারপরে আপনি জাল্ফের মন্তব্য অনুসারে শব্দ সংশোধন করা ভাল হবে
ধ্বংসকারী

1

আপনি যখন অ্যারের সাথে আরম্ভ করবেন তখন int array[2]2 পূর্ণসংখ্যার জন্য স্থান বরাদ্দ করা হয়; তবে সনাক্তকারী arrayসহজভাবে সেই জায়গার শুরুতে নির্দেশ করে। যখন আপনি তখন অ্যাক্সেস করেন array[3]এবং array[4], সংকলকটি তখন কেবল সেই ঠিকানাটি বাড়িয়ে দেয় যাতে সেই মানগুলি কোথায় হবে সেই দিকে নির্দেশ করে, যদি অ্যারেটি দীর্ঘ হয়; array[42]প্রথমে এটিকে আরম্ভ না করেই অ্যাক্সেস করার চেষ্টা করুন , আপনি ইতিমধ্যে সেই জায়গাতে স্মৃতিতে থাকা যে কোনও মানই পেয়ে যাবেন।

সম্পাদনা:

পয়েন্টার / অ্যারে সম্পর্কিত আরও তথ্য: http://home.netcom.com/~tjensen/ptr/pointers.htm


0

আপনি যখন int অ্যারে ঘোষণা করেন [2]; আপনি প্রতিটি 4 টি বাইট (32 বিট প্রোগ্রাম) এর 2 মেমরি স্পেস সংরক্ষণ করেন। আপনি যদি আপনার কোডটিতে অ্যারে [4] টাইপ করেন তবে এটি এখনও একটি বৈধ কলের সাথে মিলে যায় তবে কেবল রান টাইমে এটি একটি নিয়ন্ত্রণহীন ব্যতিক্রম ছুঁড়ে ফেলবে। সি ++ ম্যানুয়াল মেমরি পরিচালনা ব্যবহার করে। এটি আসলে একটি সুরক্ষা ত্রুটি যা হ্যাকিং প্রোগ্রামগুলির জন্য ব্যবহৃত হয়েছিল

এটি বুঝতে সহায়তা করতে পারে:

int * somepointer;

somepointer [0] = somepointer [5];


0

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


0

আপনি যখন সিটিতে 'অ্যারে [সূচক]' লেখেন এটি মেশিনের নির্দেশিকায় অনুবাদ করে।

অনুবাদটি এরকম কিছু:

  1. 'অ্যারের ঠিকানা পান'
  2. 'অ্যারে দিয়ে তৈরি বস্তুর ধরণের আকারটি পান'
  3. 'সূচী দ্বারা প্রকারের আকারটি গুন করুন'
  4. 'ফলাফল অ্যারের ঠিকানায় যুক্ত করুন'
  5. 'ফলাফলের ঠিকানায় কী রয়েছে তা পড়ুন'

ফলাফলটি এমন কোনও বিষয়কে সম্বোধন করে যা অ্যারের অংশ হতে পারে বা নাও পারে। মেশিনের নির্দেশের জ্বলন্ত গতির পরিবর্তে আপনি কম্পিউটারের জন্য কম্পিউটার পরীক্ষা করার সুরক্ষা জালটি হারাবেন। আপনি যদি সাবধান হন এবং সতর্ক হন তবে এটি কোনও সমস্যা নয়। যদি আপনি ঝাপটায় হন বা কোনও ভুল করেন তবে আপনি জ্বলে উঠবেন। কখনও কখনও এটি একটি অবৈধ নির্দেশ জেনারেট করতে পারে যা একটি ব্যতিক্রম ঘটায়, কখনও কখনও না।


0

একটি চমৎকার পদ্ধতির যা আমি প্রায়শই দেখেছি এবং আমি আসলে ব্যবহার করে আসছি তা হ'ল uint THIS_IS_INFINITY = 82862863263;অ্যারের শেষে কিছু ন্যূনুল টাইপ উপাদান (বা একটি তৈরির মতো ) ইনজেকশন করা ।

তারপরে লুপ শর্ত পরীক্ষা করে দেখুন, TYPE *pagesWordsএক ধরণের পয়েন্টার অ্যারে:

int pagesWordsLength = sizeof(pagesWords) / sizeof(pagesWords[0]);

realloc (pagesWords, sizeof(pagesWords[0]) * (pagesWordsLength + 1);

pagesWords[pagesWordsLength] = MY_NULL;

for (uint i = 0; i < 1000; i++)
{
  if (pagesWords[i] == MY_NULL)
  {
    break;
  }
}

অ্যারে structপ্রকারে ভরা থাকলে এই সমাধানটি কথা বলবে না ।


0

প্রশ্নে এখন উল্লিখিত হিসাবে std :: ভেক্টর :: এ ব্যবহার করে সমস্যার সমাধান হবে এবং অ্যাক্সেসের আগে একটি আবদ্ধ চেক করবে।

আপনার যদি প্রথম ধরণের কোড হিসাবে স্ট্যাকের উপরে অবস্থিত একটি ধ্রুবক আকারের অ্যারে প্রয়োজন হয় তবে সি ++ 11 টি নতুন স্ট্যান্ডার্ড :: অ্যারে ব্যবহার করুন; ভেক্টর হিসাবে এখানে স্ট্যান্ড :: অ্যারে :: ফাংশনে আছে। প্রকৃতপক্ষে ফাংশনটি সমস্ত স্ট্যান্ডার্ড পাত্রে রয়েছে যার এটির একটি অর্থ রয়েছে, অর্থাত্, যেখানে অপারেটর [] সংজ্ঞায়িত :( ডেক, মানচিত্র, আনর্ডারড_ম্যাপ) ব্যতীত স্ট্যান্ড :: বিটসেটকে একে স্ট্যান্ড :: বিটসেট বলা হয়: : পরীক্ষা।


0

libstdc ++, যা জিসিসির অংশ, ত্রুটি পরীক্ষার জন্য একটি বিশেষ ডিবাগ মোড রয়েছে । এটি সংকলক পতাকা দ্বারা সক্ষম করা হয়েছে -D_GLIBCXX_DEBUG। অন্যান্য কাজের মধ্যে এটি std::vectorপারফরম্যান্সের ব্যয়ে চেক করতে সীমাবদ্ধ । এখানে জিসিসির সাম্প্রতিক সংস্করণ সহ অনলাইন ডেমো রয়েছে।

সুতরাং বাস্তবে আপনি libstdc ++ ডিবাগ মোডের সাহায্যে বাউন্ড চেক করতে পারেন তবে পরীক্ষার সময় আপনার এটি করা উচিত কারণ এটি সাধারণ libstdc ++ মোডের তুলনায় উল্লেখযোগ্য পারফরম্যান্সের জন্য ব্যয় করে।


0

আপনি যদি আপনার প্রোগ্রামটি কিছুটা পরিবর্তন করেন:

#include <iostream>
using namespace std;
int main()
{
    int array[2];
    INT NOTHING;
    CHAR FOO[4];
    STRCPY(FOO, "BAR");
    array[0] = 1;
    array[1] = 2;
    array[3] = 3;
    array[4] = 4;
    cout << array[3] << endl;
    cout << array[4] << endl;
    COUT << FOO << ENDL;
    return 0;
}

(রাজধানীগুলির পরিবর্তন - আপনি যদি এটি চেষ্টা করতে যাচ্ছেন তবে সেগুলি নিম্নতর ক্ষেত্রে রাখুন))

আপনি দেখতে পাবেন যে ভেরিয়েবল foo ট্র্যাশ হয়ে গেছে। আপনার কোডটি অস্তিত্বযুক্ত অ্যারে [3] এবং অ্যারে [4] এ মান সংরক্ষণ করবে এবং সেগুলি যথাযথভাবে পুনরুদ্ধার করতে সক্ষম হবে, তবে ব্যবহৃত প্রকৃত সঞ্চয়স্থান হবে ফু থেকে ।

সুতরাং আপনি আপনার মূল উদাহরণে অ্যারের সীমা অতিক্রম করে "পালাতে" পারেন তবে অন্য কোথাও ক্ষতির কারণ হতে পারে - এমন ক্ষতি যা নির্ণয় করা খুব কঠিন বলে প্রমাণিত হতে পারে ।

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

সি ++ সি এর উপর ভিত্তি করে তৈরি করা হয়েছে, যা যতটা সম্ভব এসেম্বলি ভাষার কাছাকাছি হওয়ার জন্য ডিজাইন করা হয়েছিল।

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