অবশেষে ভিতরে একটি ব্যতিক্রম ছোঁড়া


27

দৃঢ় মত স্ট্যাটিক কোড বিশ্লেষক "অভিযোগ" একটি ব্যতিক্রম একটি ভিতরে নিহিত করা যেতে পারে যখন finallyব্লক, বলে যে Using a throw statement inside a finally block breaks the logical progression through the try-catch-finally। সাধারণত আমি এটির সাথে একমত হই। তবে সম্প্রতি আমি এই কোডটি পেরিয়ে এসেছি:

SomeFileWriter writer = null; 
try { 
     //init the writer
     //write into the file
} catch (...) {
     //exception handling
} finally {
     if (writer!= null) writer.close();  
}

এখন যদি writerসঠিকভাবে বন্ধ না করা যায় তবে writer.close()পদ্ধতিটি একটি ব্যতিক্রম ছুঁড়ে দেবে। একটি ব্যতিক্রম নিক্ষেপ করা উচিত কারণ (সম্ভবত) ফাইলটি লেখার পরে সংরক্ষণ করা হয়নি।

আমি একটি অতিরিক্ত ভেরিয়েবল ঘোষণা করতে পারতাম, এটি বন্ধ করতে কোনও ত্রুটি থাকলে এটি সেট করতে পারি writerএবং শেষ পর্যন্ত ব্লকের পরে একটি ব্যতিক্রম ছুঁড়ে দেয়। তবে এই কোডটি কার্যকরভাবে কাজ করে এবং আমি এটি পরিবর্তন করব কিনা তা নিশ্চিত নই।

finallyব্লকের ভিতরে একটি ব্যতিক্রম ছোঁড়ার অসুবিধাগুলি কী কী ?


4
যদি এটি জাভা হয়, এবং আপনি জাভা 7 ব্যবহার করতে পারেন, এটিএম ব্লকগুলি আপনার সমস্যার সমাধান করতে পারে কিনা তা পরীক্ষা করে দেখুন।
লন্ডেই 12

@ ল্যান্ডই, এটি সমাধান করে তবে দুর্ভাগ্যক্রমে আমরা জাভা using ব্যবহার করছি না
সুপারম

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

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

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

উত্তর:


18

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

কিছু লোক নেস্টেড ব্যতিক্রম হ্যান্ডলারের একটি বাজে প্যাটার্ন অনুসরণ করে, finallyব্লকে ফেলে দেওয়া কোনও ব্যতিক্রম গিলে ফেলে ।

SomeFileWriter writer = null; 
try { 
     //init the writer
     //write into the file
} finally {
    if (writer!= null) {
        try {
            writer.close();
        } catch (...) {
        }
    }
}

জাভার পুরানো সংস্করণগুলিতে, আপনি ক্লাসগুলিতে এই "নিরাপদ" ক্লিন আপগুলি সংস্থান করে এমন কোডগুলি "সরলকরণ" করতে পারেন। আমার এক ভাল বন্ধু বেনামে প্রকারের একটি তালিকা তৈরি করে, যার প্রত্যেকটি তাদের সংস্থানগুলি পরিষ্কার করার জন্য যুক্তি সরবরাহ করে। তারপরে তার কোডটি কেবল তালিকার উপরে লুপ করে এবং finallyব্লকের মধ্যে নিষ্পত্তি পদ্ধতিটিকে কল করে ।


1
+1 যদিও আমি সেইসব বাজে কোড ব্যবহার করি তাদের মধ্যে রয়েছি। তবে আমার ন্যায্যতার জন্য আমি বলব যে আমি সর্বদা এটি করি না, কেবল তখনই ব্যতিক্রমটি সমালোচিত হয় না।
সুপারম

2
আমি নিজেও এটি করে দেখছি। কিছু সময় কোনও পুরো রিসোর্স ম্যানেজার তৈরি করা (নামবিহীন বা না) কোডের উদ্দেশ্য থেকে আলাদা করে।
ট্র্যাভিস পার্কস

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

1
একটি অবশেষে ব্লকের মধ্যে চেষ্টা / ক্যাচ ব্লক ব্যবহার সম্পর্কে এত বাজে কী? আমি বরং আমার সমস্ত সংযোগ এবং স্ট্রিম ইত্যাদি গুটিয়ে রেখে আমার কোডটি ফুটিয়ে তোলার চেয়ে কেবল তাই করব যে এগুলি চুপচাপ বন্ধ করা যেতে পারে - যা নিজেই কোনও সংযোগ বা স্ট্রিম বন্ধ করে রাখার বিষয়টি না জানার একটি নতুন সমস্যা প্রবর্তন করে ( বা যাই হোক না কেন) একটি ব্যতিক্রম ঘটায় - যা এমন কিছু যা আপনি আসলে সম্পর্কে জানতে বা কিছু করতে পছন্দ করতে পারেন ...
নিষেধাজ্ঞায়িত-জায়োঞ্জিনিয়ারিং

10

ট্র্যাভিস পার্ক যা বলেছিল তা সত্য যে finallyব্লকের ব্যতিক্রমগুলি try...catchব্লকগুলি থেকে কোনও রিটার্ন মান বা ব্যতিক্রম গ্রহণ করবে ।

আপনি যদি জাভা 7 ব্যবহার করেন তবে রিসোর্স ব্লক ব্যবহার করে সমস্যাটি সমাধান করা যেতে পারে । দস্তাবেজগুলির মতে, যতক্ষণ না আপনার সংস্থানগুলি কার্যকর হয় java.lang.AutoCloseable(বেশিরভাগ গ্রন্থাগার লেখক / পাঠক এখনই করেন) ততক্ষণ -রিসোর্স ব্লকটি আপনার জন্য এটি বন্ধ করে দেবে। এখানে অতিরিক্ত সুবিধা হ'ল এটি বন্ধ করার সময় যে কোনও ব্যতিক্রম ঘটে তা দমন করা হবে, মূল ফেরতের মান বা ব্যতিক্রমটি পাস করার অনুমতি দেয়।

থেকে

FileWriter writer = null;
try {
  writer = new FileWriter("myFile.txt");
  writer.write("hello");
} catch(...) {
  // return/throw new exception
} finally {
  writer.close(); // an exception would consume the catch block's return/exception
}

থেকে

try (FileWriter writer = new FileWriter("myFile.txt")) {
  writer.write("hello");
} catch(...) {
  // return/throw new exception, always gets returned even if writer fails to close
}

http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html


1
এটি কখনও কখনও সহায়ক হয়। তবে ফাইলটি বন্ধ করা যায় না এমন ক্ষেত্রে যখন আমার আসলে একটি ব্যতিক্রম ছুঁড়ে ফেলার প্রয়োজন হয় তখন এই পদ্ধতির সমস্যাগুলি আড়াল করে।
সুপারম

1
@superM বাস্তবিক, চেষ্টা-সঙ্গে-সম্পদ থেকে একটি ব্যতিক্রম লুকায় না close()। "এটি বন্ধ করার সময় যে কোনও ব্যতিক্রম ঘটে তা দমন করা হবে, মূল রিটার্ন মান বা ব্যতিক্রমটি পাস করার অনুমতি দেয়" - এটি কেবল সত্য নয়close()পদ্ধতি থেকে একটি ব্যতিক্রম কেবল তখনই চাপা দেওয়া হবে যখন চেষ্টা / ক্যাচ ব্লক থেকে অন্য ব্যতিক্রম ছুঁড়ে ফেলা হবে। সুতরাং, যদি tryব্লকটি কোনও ব্যতিক্রম ছুঁড়ে না ফেলে, তবে close()পদ্ধতি থেকে ব্যতিক্রম নিক্ষেপ করা হবে (এবং ফেরতের মান ফিরে আসবে না)। এমনকি এটি বর্তমান catchব্লক থেকে পাওয়া যায় ।
রুসলান স্টেলমাচেনকো

0

আমি মনে করি এটি এমন একটি বিষয় যা আপনার কেস ভিত্তিতে কেস ভিত্তিতে সম্বোধন করতে হবে। কিছু ক্ষেত্রে বিশ্লেষক যা বলছেন তা সঠিক কারণ আপনার কাছে কোডটি দুর্দান্ত নয় এবং এর জন্য পুনর্বিবেচনা প্রয়োজন। তবে নিক্ষেপ করা বা পুনরায় নিক্ষেপ করা যখন অন্য জিনিস হতে পারে তখন এটি সবচেয়ে ভাল জিনিস হতে পারে। এটি হ্যান্ডেট করার মতো কিছু নয়।


0

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

ত্রুটি রিকভারি ব্যর্থ হতে পারে না

finally কোনও লেনদেন সফল হয় বা ব্যর্থ হয় নির্বিশেষে নির্বাহ করা হয় এমন একটি লেনদেনের পরে নিয়ন্ত্রণ প্রবাহকে মডেল করে।

ব্যর্থ ক্ষেত্রে, এটি সম্পূর্ণরূপে সেরে ওঠার আগে (আমরা আমাদের গন্তব্যে পৌঁছানোর আগে ) কোনও ত্রুটি থেকে পুনরুদ্ধারের মাঝখানেfinally মৃত্যুদন্ড কার্যকর করা যুক্তিটি ক্যাপচার করে ।catch

কোনও ত্রুটি থেকে পুনরুদ্ধারের মাঝামাঝি একটি ত্রুটির মুখোমুখি হওয়ার জন্য এটি যে ধারণামূলক সমস্যাটি উপস্থাপন করে তা কল্পনা করুন ।

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

এই ধারণাগত সমস্যা কোন ভাষায় বিদ্যমান ত্রুটিযুক্ত পুলিশ কিনা ম্যানুয়াল ত্রুটি কোড প্রসারণ সঙ্গে এটি এর সি, বা সি ++ ব্যতিক্রম এবং destructors, অথবা ব্যতিক্রম এবং জাভা সঙ্গে finally

finally যে ভাষাগুলি এগুলিকে একইভাবে সরবরাহ করে তাতে ব্যর্থতা ঘটতে পারে না ব্যতিক্রমগুলির মুখোমুখি হওয়ার প্রক্রিয়ায় ডেস্ট্রাক্টররা সি ++ এ ব্যর্থ হতে পারে না।

এই ধারণাগত এবং কঠিন সমস্যা এড়ানোর একমাত্র উপায় হ'ল নিশ্চিত করা যে লেনদেনকে ফিরিয়ে আনার এবং মাঝখানে রিসোর্সগুলি ছাড়ার প্রক্রিয়াটি সম্ভবত পুনরাবৃত্ত ব্যতিক্রম / ত্রুটির মুখোমুখি হতে পারে না।

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

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

উদাহরণ: লগিং

ধরা যাক আপনি একটি finallyব্লকের ভিতরে স্টাফ লগ করতে চান । লগিং ব্যর্থ না হতে পারে এটি প্রায়শই একটি বিশাল সমস্যা হতে চলেছে । লগ ইন করা প্রায়শই ব্যর্থ হতে পারে, যেহেতু এটি ফাইলটিতে আরও ডেটা যুক্ত করতে পারে এবং এটি ব্যর্থ হওয়ার অনেকগুলি কারণ সহজেই খুঁজে পেতে পারে।

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

এই ক্ষেত্রে, লগিং ব্যর্থতা দিয়ে আমরা দূরে সরে যেতে পারি তবে শর্ত থাকে যে এটি লগ করতে ব্যর্থ হয়েছে এবং কিছুই না করে বিশ্বের শেষ নয় (এটি কোনও সংস্থান ফাঁস করে না বা পার্শ্ব প্রতিক্রিয়াগুলি ব্যর্থ করতে ব্যর্থ হয়, যেমন)।

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

SomeFileWriter

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

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

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