setjmp এবং longjmp হলো সি-তে নন-লোকাল গোটো (non-local goto) বা প্রিমিটিভ এক্সসেপশন হ্যান্ডলিং মেকানিজম। এটি <setjmp.h> হেডারে ডিক্লেয়ার করা থাকে।
ফাংশন সিগনেচার
int setjmp(jmp_buf env); // এনভায়রনমেন্ট সেভ করে, প্রথম কলেই ০ রিটার্ন
void longjmp(jmp_buf env, int val); // env-এ ফিরে যায়, setjmp কে val রিটার্ন করিয়ে দেয়
কিভাবে কাজ করে
setjmp(buf)কল করলে বর্তমান স্ট্যাক কনটেক্সট (প্রোগ্রাম কাউন্টার, স্ট্যাক পয়েন্টার, রেজিস্টার ইত্যাদি)buf-এ সেভ হয় এবং0রিটার্ন করে- নরমাল এক্সিকিউশন চালিয়ে যায়
- যখন
longjmp(buf, val)কল হয়, প্রোগ্রাম সংরক্ষিতbuf-এ জাম্প করে setjmpদ্বিতীয়বারvalরিটার্ন করে (যদিval == 0হয় তবে1রিটার্ন করে)
উদাহরণ: ১০০ বার প্রিন্ট (লুপ ছাড়া)
#include <stdio.h>
#include <setjmp.h>
jmp_buf buf;
int main() {
int x = 1;
setjmp(buf);
printf("5");
x++;
if (x <= 100)
longjmp(buf, 1);
return 0;
}
আউটপুট
5555555555555555555555555555555555555555555555555555555555555555555555555555
555555555555555555555555
ব্যবহার ক্ষেত্র
- গভীর নেস্টেড ফাংশন কল থেকে দ্রুত বের হওয়া (Error handling in parsers, VMs)
- কোরুটিন/গ্রিন থ্রেড বাস্তবায়ন
- সিগন্যাল হ্যান্ডলার থেকে মেইন প্রোগ্রামে ফেরত যাওয়া
বিশেষ সতর্কতা (C++-এ অত্যন্ত বিপজ্জনক) ⚠️
C++-এ setjmp/longjmp ব্যবহার করবেন না।
- স্ট্যাক আনওয়াইন্ডিং হয় না — ডেস্ট্রাক্টর কল হয় না
- RAII ভেঙে যায় (রিসোর্স লিক, লক লিক, মেমরি লিক)
- অবজেক্ট লাইফটাইম ম্যানেজমেন্ট ভেঙে যায়
- C++-এ
try/catch/throwব্যবহার করুন
সি-এ সতর্কতা
- VLA (Variable Length Array) বা ভেরিয়েবল যা
setjmp-এর পরে মডিফাই হয়,longjmp-এর পরে তাদের মান অনডিফাইনড হতে পারে volatileকীওয়ার্ড দিয়ে ভেরিয়েবল ডিক্লেয়ার করলে মান সংরক্ষিত থাকে- সিগন্যাল হ্যান্ডলার থেকে
longjmpকল করলে অ্যাসিনক্রোনাস সিগন্যাল সেফ ফাংশন ব্যবহার করতে হবে
উপসংহার
শিক্ষামূলক/লিগ্যাসি সি কোড ছাড়া আধুনিক প্রোগ্রামিং-এ এটা এড়িয়ে চলা ভালো।