কিভাবে সি একটি ব্যতিক্রম নিক্ষেপ?


106

আমি এটিকে গুগলে টাইপ করেছি তবে কেবল সি ++ তে হাওটো পেয়েছি,

এটি সি তে কীভাবে করবেন?


8
সি ব্যতিক্রম হ্যান্ডলিং সমর্থন করে না। সি-তে একটি ব্যতিক্রম ছুঁড়ে ফেলার জন্য আপনাকে উইন 32 এর কাঠামোগত ব্যতিক্রম হ্যান্ডলিংয়ের মতো নির্দিষ্ট কিছু প্ল্যাটফর্ম ব্যবহার করতে হবে - তবে এটির জন্য কোনও সহায়তা দেওয়ার জন্য আমাদের আপনার যে প্ল্যাটফর্মটি যত্নশীল তা জানতে হবে।
জেরি কফিন

18
... এবং উইন 32 স্ট্রাকচার্ড ব্যতিক্রম হ্যান্ডলিং ব্যবহার করবেন না।
ব্রায়ান আর বন্ডি

4
সেটজ্যাম্প () এবং লংজ্যাম্প () ব্যবহার করে, তাত্ত্বিকভাবে, কাজ করা উচিত, তবে আমি মনে করি এটি সমস্যার পক্ষে উপযুক্ত নয়।
জোসেফ কুইনসে

উত্তর:


80

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

ব্যতিক্রমগুলি সি ++ এবং অন্যান্য ভাষায় যদিও সংজ্ঞায়িত করা হয়। সি ++ এ ব্যতিক্রম হ্যান্ডলিং সি ++ স্ট্যান্ডার্ড "এস .15 ব্যতিক্রম হ্যান্ডলিং" এ সুনির্দিষ্ট করা হয়েছে, সি স্ট্যান্ডার্ডে কোনও সমমানের বিভাগ নেই।


4
সুতরাং সি এটি গ্যারান্টিযুক্ত আছে ব্যতিক্রম হবে না, কিভাবে?
HTTP ব্যাখ্যা করুন

65
@httpinter ব্যাখ্যা: সিতে এটি "গ্যারান্টেড" যে কোনওভাবেই ব্যতিক্রম নেই যে এটি "গ্যারান্টেড" যে কোনও টেমপ্লেট, বা কোনও প্রতিবিম্ব বা কোনও ইউনিকর্ন নেই। ভাষার স্পেসিফিকেশন কেবল এই জাতীয় কোনও সংজ্ঞা দেয় না। সেখানে সেটজ্যাম্প / লংজ্যাম্প রয়েছে, যা কোনও ফাংশন ছাড়ার জন্য ব্যবহার না করে ব্যবহার করা যেতে পারে। সুতরাং প্রোগ্রামগুলি তারা চাইলে তাদের নিজস্ব ব্যতিক্রমের মতো প্রক্রিয়া তৈরি করতে পারে বা একটি সি বাস্তবায়ন স্ট্যান্ডার্ডের সাথে এক্সটেনশনগুলি সংজ্ঞায়িত করতে পারে।
স্টিভ জেসোপ

4
mainএকটি .cফাইল সহ একটি প্রোগ্রামে কিছু সি ++ অন্তর্ভুক্ত থাকতে পারে, এবং তাই ব্যতিক্রমগুলি প্রোগ্রামে ছুঁড়ে ফেলা এবং ধরা যেতে পারে তবে সি কোডের অংশগুলি সি ব্যতীত ফেলে দেওয়া এবং ধরা প্রায়শই সিটিতে লিখিত ফাংশনগুলির উপর নির্ভর করে ব্যতীত এই সমস্ত কিছু সম্পর্কে অজ্ঞ থাকবে will যা সি ++ লাইব্রেরিতে থাকে। সি ব্যবহার করা হয়েছে কারণ আপনি throwব্যতিক্রম নিজেই নিক্ষেপ করার জন্য ডাকা ফাংশনটি ঝুঁকিপূর্ণ করতে পারবেন না । যদিও একটি সংকলক / গ্রন্থাগার / লক্ষ্য ব্যতীত ছোঁড়া / ধরতে ব্যতিক্রম নির্দিষ্ট উপায় থাকতে পারে। তবে একটি ক্লাস উদাহরণ নিক্ষেপ করার নিজস্ব সমস্যা থাকবে।
শনিবার 21 '20

61
@ স্টিভ: দয়া করে আপনি আমাকে জানাবেন যদি আপনি ইউনিকর্নযুক্ত কোনও ভাষা খুঁজে পান তবে আমি বছরের পর বছর ধরে এই জাতীয় একটি অপেক্ষায় ছিলাম।
ব্রায়ান আর বন্ডি

5
@ ব্রায়ানআর.বন্ডি এখানে ইউনিকর্নযুক্ত একটি ভাষা রয়েছে (আমি এটি গ্যারান্টির সাথে একইভাবে গ্যারান্টি
দিচ্ছি

38

সি তে আপনি সংজ্ঞায়িত setjmp()এবং longjmp()ফাংশনগুলির সংমিশ্রণটি ব্যবহার করতে পারেন setjmp.hউইকিপিডিয়া থেকে উদাহরণ

#include <stdio.h>
#include <setjmp.h>

static jmp_buf buf;

void second(void) {
    printf("second\n");         // prints
    longjmp(buf,1);             // jumps back to where setjmp 
                                //   was called - making setjmp now return 1
}

void first(void) {
    second();
    printf("first\n");          // does not print
}

int main() {   
    if ( ! setjmp(buf) ) {
        first();                // when executed, setjmp returns 0
    } else {                    // when longjmp jumps back, setjmp returns 1
        printf("main");         // prints
    }

    return 0;
}

দ্রষ্টব্য: আমি আসলে আপনাকে পরামর্শ দেব যে তারা সি ++ (স্থানীয় বস্তুর ধ্বংসকারীদের ডাকা হবে না) নিয়ে ভয়ঙ্কর কাজ করার কারণে সেগুলি ব্যবহার না করার জন্য এবং কী চলছে তা বোঝা সত্যিই শক্ত। পরিবর্তে কিছু ধরণের ত্রুটি ফিরিয়ে দিন।


আমি দেখেছি যে সেটজাম্প / লংজাম্প সি ++ প্রোগ্রামগুলিতে সঠিকভাবে কাজ করে না এমনকি যখন ব্যতিক্রমগুলি ব্যবহার করার সময় ধ্বংসের প্রয়োজন হয় এমন কোনও বস্তু নেই। আমি এগুলি খুব কমই সি প্রোগ্রামগুলিতে ব্যবহার করি।
শনিবার 21'

সেটজেম্প ব্যবহার করে এটি একটি আকর্ষণীয় পন্থা ছিল। on-time.com/ddj0011.htm তবে হ্যাঁ, মুলত আপনি যদি স্ট্যাকটি অনিচ্ছাকৃত না করে আউট-অফ-ব্যান্ড কোড সম্পাদন করতে চান তবে আপনাকে সেগুলি নিজেরাই আবিষ্কার করতে হবে।
ডোয়াইন রবিনসন

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

4
যাইহোক, ব্যতিক্রম হ্যান্ডলিং এমন কিছু ছিল যা আমি সত্যিই আশা করছিলাম যে সি 11 এ শেষ হত। সাধারণ বিশ্বাস থাকা সত্ত্বেও, এটি সঠিকভাবে কাজ করার জন্য ওওপির প্রয়োজন হয় না এবং সি এর প্রতিটি ক্রিয়াকলাপের জন্য অবিরাম ক্ষতিগ্রস্থ হয় if()। আমি এতে কোনও বিপদ দেখতে পাচ্ছি না; এখানে অন্য কেউ করতে পারেন?

@ user4229245 আমি (উপাচার্য) ছাপের আওতায় আছি "আপনার জন্য যা কিছু করা হয়েছে" সি ভাষার ভাষার বাইরে রাখা হয়েছে বিশেষত খালি ধাতু এবং মেশিন প্রোগ্রামিংয়ের জন্য সি প্রাসঙ্গিক রাখতে যেখানে আট বিট বাইট আইনের মতো স্থিতিকালিক মৌলিক বিষয়গুলিও status সর্বজনীন নয়, কেবল আমার চিন্তাভাবনা, আমি কোনও গ
স্প

21

সরল পুরানো সি বাস্তবে ব্যাতিক্রমকে সমর্থন করে না।

আপনি বিকল্প ত্রুটি পরিচালনার কৌশলগুলি ব্যবহার করতে পারেন, যেমন:

  • একটি ত্রুটি কোড ফেরত
  • ফিরে আসার FALSEএবং একটি last_errorভেরিয়েবল বা ফাংশন ব্যবহার করে ।

Http://en.wikibooks.org/wiki/C_Programming/Error_handling দেখুন ।


উইন্ডোজ এপিও এরোর পরিচালনা করার জন্য একই পদ্ধতি রয়েছে। উদাহরণস্বরূপ GetLastError()উইন্ডোজ এপিআই তে
যুদ্ধক্ষেত্র

20

সি -তে কোনও অন্তর্নির্মিত ব্যতিক্রম ব্যবস্থা নেই; আপনাকে ব্যতিক্রম এবং তাদের শব্দার্থবিজ্ঞানের অনুকরণ করতে হবে । সাধারণত setjmpএবং উপর নির্ভর করে এটি অর্জন করা হয় longjmp

চারপাশে বেশ কয়েকটি গ্রন্থাগার রয়েছে এবং আমি আরও একটি বাস্তবায়ন করছি। একে ব্যতিক্রম 4c বলা হয় ; এটি বহনযোগ্য এবং বিনামূল্যে। আপনি এটি একবার দেখে নিতে পারেন এবং এটি আপনার অন্যান্য ক্ষেত্রে সবচেয়ে উপযুক্ত কিনা তা দেখতে অন্যান্য বিকল্পের সাথে তুলনা করতে পারেন।


আমি আপনার কোড উদাহরণটি পড়েছি, আমি একই কাঠামো দিয়ে প্রকল্প শুরু করেছি, তবে প্রতিটি "ব্যতিক্রম" সনাক্ত করতে স্ট্রিংয়ের পরিবর্তে একটি ইউইড ব্যবহার করি। আপনার প্রকল্পটি খুব আশাব্যঞ্জক বলে মনে হচ্ছে।
ইউএমএলকেট

বিকল্প লিঙ্ক এখন নির্দেশ করা উচিত github.com/guillermocalvo/exceptions4c/wiki/alternatives
মার্সেল Waldvogel

আপনি (বা অন্য কেউ) বিভিন্ন ব্যতিক্রম প্যাকেজগুলির মধ্যে একটি তুলনা সম্পর্কে জানেন?
মার্সেল ওয়াল্ডভোগেল

11

সি সি ++ ব্যতিক্রম ছুঁড়ে ফেলতে সক্ষম, এগুলি যাইহোক মেশিন কোড। উদাহরণস্বরূপ, বার

// begin bar.c
#include <stdlib.h>
#include <stdint.h>
extern void *__cxa_allocate_exception(size_t thrown_size);
extern void __cxa_throw (void *thrown_exception, void* *tinfo, void (*dest) (void *) );
extern void * _ZTIl; // typeinfo of long
int bar1()
{
   int64_t * p = (int64_t*)__cxa_allocate_exception(8);
   *p = 1976;
   __cxa_throw(p,&_ZTIl,0);
  return 10;
}
// end bar.c

a.cc এ,

#include <stdint.h>
#include <cstdio>
extern "C" int bar1();
void foo()
{
  try{
    bar1();
  }catch(int64_t x){
    printf("good %ld",x);
  }
}
int main(int argc, char *argv[])
{
  foo();
  return 0;
}

এটি সংকলন করতে

gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out

আউটপুট

good 1976

http://mentore এম্বেড.github.io/cxx-abi/abi-eh.html সম্পর্কে আরও বিশদ তথ্য আছে __cxa_throw

এটি পোর্টেবল কিনা তা আমি নিশ্চিত নই এবং আমি এটি লিনাক্সে 'gcc-4.8.2' দিয়ে পরীক্ষা করি।


4
"_ জেডটিআইএল" কি? ??? আমি এর কোথাও কোনও রেফারেন্স খুঁজে পাচ্ছি না এবং এটি সি সি কোডের জন্য স্ট্যান্ড :: টাইপ_ইনফোর অ্যাক্সেসকে কীভাবে সম্ভব করবে এটি একটি সম্পূর্ণ রহস্য। আমাকে সাহায্য করুন!
আরিউসআস্টার্টে

4
_ZTIIঅর্থ typeinfo for long, যেমন echo '_ZTIl' | c++filt । এটি জি ++ ম্যাংলিং স্কিম।
wcy

এবং কেবলমাত্র ভাল পরিমাপের জন্য সি ++ যতটা সম্ভব এড়াতে ক্যাচ ব্লকে AC চিহ্নটি কল করতে ভুলবেন না: পি (চমত্কার আসল উদাহরণ ভাগ করে নেওয়ার জন্য পিএস আপনাকে ধন্যবাদ!)
থারস্মমনার

8

এই প্রশ্নটি বেশ পুরানো, তবে আমি কেবল এটির পিছনে হোঁচট খেয়েছি এবং ভেবেছিলাম যে আমি কোনও কৌশল ভাগ করব: শূন্য দ্বারা ভাগ করুন, বা একটি নাল পয়েন্টারকে অবজ্ঞা করুন।

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


@ আরুসআস্টার্টে কেবলমাত্র যদি কাউকে সত্যিই শূন্যের মাধ্যমে একটি বিভাগ দেখানো প্রয়োজন:int div_by_nil(int x) { return x/0; }

7

এমএসভিসির সাথে উইন এ রয়েছে __try ... __except ...তবে এটি সত্যই ভয়ঙ্কর এবং আপনি যদি এটিকে সম্ভবত এড়াতে পারেন তবে আপনি এটি ব্যবহার করতে চান না। বলাই ভাল যে এর ব্যতিক্রম নেই।


4
আসলে সি ++ ব্যতিক্রমগুলি হুডের নীচেও এসইএইচ শীর্ষে নির্মিত হয়।
কলমারিয়াস


4
@ মার্সেলওয়াল্ডভোভেল স্ট্রাকচার্ড এক্সসেপশন হ্যান্ডলিং (সিপিইউ ব্যতিক্রমগুলি পরিচালনা করার উইন্ডোজের উপায়)।
কলমারিয়াস

6

সি এর ব্যতিক্রম নেই।

বিভিন্ন হ্যাকি বাস্তবায়ন রয়েছে যা এটি করার চেষ্টা করে (একটি উদাহরণ: http://adomas.org/excc/ )।


3

অসংখ্য থ্রেডে উল্লিখিত হিসাবে, এটি করার "স্ট্যান্ডার্ড" উপায়টি সেটজেম্প / লংজ্যাম্প ব্যবহার করছে। আমি https://github.com/psevon/exception-and-raii-in-c- তে এর পরে আর একটি সমাধান পোস্ট করেছি এটি আমার জ্ঞানের একমাত্র সমাধান যা বরাদ্দকৃত সংস্থানগুলি স্বয়ংক্রিয়ভাবে পরিষ্কারের উপর নির্ভর করে। এটি অনন্য এবং ভাগ করা স্মার্টপোয়েন্টারগুলি প্রয়োগ করে এবং মধ্যবর্তী ফাংশনগুলি ব্যতিক্রমগুলি ধরে না ফেলে এবং তাদের স্থানীয়ভাবে বরাদ্দকৃত সম্পদগুলি সঠিকভাবে পরিষ্কার করার অনুমতি দেয় properly


2

সি ব্যতিক্রমগুলি সমর্থন করে না। আপনি আপনার সি কোডটি ভিজ্যুয়াল স্টুডিও বা জি ++ দিয়ে সি ++ হিসাবে সংকলনের চেষ্টা করতে পারেন এবং এটি যেমন রয়েছে তেমন সংকলন করবে কিনা তা দেখতে পারেন। বেশিরভাগ সি অ্যাপ্লিকেশনগুলি বড় পরিবর্তন ছাড়াই সি ++ হিসাবে সংকলন করবে এবং আপনি তারপরে ... চেষ্টা বাক্যটি ব্যবহার করতে পারেন।


0

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

int process(int port)
{
    int rc;
    int fd1;
    int fd2;

    fd1 = open("/dev/...", ...);
    if (fd1 == -1) {
      rc = -1;
      goto out;
    }

    fd2 = open("/dev/...", ...);
    if (fd2 == -1) {
      rc = -1;
      goto out;
    }

    // Do some with fd1 and fd2 for example write(f2, read(fd1))

    rc = 0;

   out:

    //if (rc != 0) {
        (void)close(fd1);
        (void)close(fd2);
    //}

    return rc;
}

এটি আসলে ব্যতিক্রম হ্যান্ডলারটি করে না তবে ফুকশন প্রস্থান করার সময় ত্রুটিটি হ্যান্ডেল করার জন্য আপনাকে একটি উপায় অবলম্বন করে।

পিএস আপনার কেবল একই বা আরও গভীর স্কোপগুলি থেকে সতর্কতার সাথে ব্যবহার করা উচিত এবং ভেরিয়েবলের ঘোষণাকে কখনই লাফাতে না পারে।


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