ฉันพิมพ์สิ่งนี้ลงใน Google แต่พบเฉพาะ howtos ใน C ++
วิธีการทำใน C?
ฉันพิมพ์สิ่งนี้ลงใน Google แต่พบเฉพาะ howtos ใน C ++
วิธีการทำใน C?
คำตอบ:
ไม่มีข้อยกเว้นใน C. ใน C ข้อผิดพลาดจะได้รับแจ้งจากค่าที่ส่งคืนของฟังก์ชันค่าออกของกระบวนการส่งสัญญาณไปยังกระบวนการ ( สัญญาณข้อผิดพลาดของโปรแกรม (GNU libc) ) หรือการหยุดชะงักของฮาร์ดแวร์ CPU (หรือการแจ้งเตือนอื่น ๆ เกิดข้อผิดพลาดจาก CPU หากมี) ( ตัวประมวลผลจัดการกรณีการหารด้วยศูนย์อย่างไร )
มีการกำหนดข้อยกเว้นใน C ++ และภาษาอื่น ๆ การจัดการข้อยกเว้นใน C ++ ระบุไว้ในมาตรฐาน C ++ "การจัดการข้อยกเว้น S.15" ไม่มีส่วนที่เทียบเท่าในมาตรฐาน C
main
อยู่ใน.c
ไฟล์สามารถรวม C ++ ได้ดังนั้นจึงอาจมีการโยนและจับข้อยกเว้นในโปรแกรมได้ แต่ส่วนของรหัส C จะยังคงเพิกเฉยต่อสิ่งที่เกิดขึ้นทั้งหมดนี้ยกเว้นว่าการโยนและการจับข้อยกเว้นมักอาศัยฟังก์ชันที่เขียนด้วย C ซึ่งอยู่ในไลบรารี C ++ C ถูกใช้เนื่องจากคุณไม่สามารถเสี่ยงกับฟังก์ชันที่เรียกว่าthrow
ต้องทำโดยต้องทิ้งข้อยกเว้นเอง อาจมีวิธีเฉพาะของคอมไพเลอร์ / ไลบรารี / กำหนดเป้าหมายในการโยน / จับข้อยกเว้น แต่การโยนอินสแตนซ์คลาสจะมีปัญหาในตัวเอง
ใน C คุณสามารถใช้การรวมกันของsetjmp()
และlongjmp()
ฟังก์ชันที่กำหนดไว้ในsetjmp.h
. ตัวอย่างจาก Wikipedia
#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;
}
หมายเหตุ:ฉันอยากจะแนะนำให้คุณอย่าใช้มันเพราะมันทำงานได้แย่กับ C ++ (ผู้ทำลายวัตถุในพื้นที่จะไม่ถูกเรียก) และมันยากที่จะเข้าใจว่าเกิดอะไรขึ้น ส่งกลับข้อผิดพลาดบางอย่างแทน
if()
ไฟล์. ฉันมองไม่เห็นอันตรายในนั้น มีใครอยู่ที่นี่ได้ไหม
GetLastError()
ใน windows API
ไม่มีในตัวกลไกการยกเว้นใน C; คุณต้องจำลองข้อยกเว้นและความหมาย โดยปกติจะทำได้โดยอาศัยsetjmp
และlongjmp
และ
มีห้องสมุดอยู่ไม่กี่แห่งและฉันกำลังใช้งานอีกแห่งหนึ่ง เรียกว่าexceptions4c ; แบบพกพาและฟรี คุณอาจลองดูและเปรียบเทียบกับทางเลือกอื่นเพื่อดูว่าตัวเลือกใดเหมาะกับคุณมากที่สุด
C สามารถโยนข้อยกเว้น C ++ ได้ซึ่งเป็นรหัสเครื่องอยู่ดี ตัวอย่างเช่นใน bar.c
// 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://mentorembedded.github.io/cxx-abi/abi-eh.htmlมีข้อมูลรายละเอียดเพิ่มเติมเกี่ยวกับ__cxa_throw
มีข้อมูลรายละเอียดเพิ่มเติมเกี่ยวกับ
ฉันไม่แน่ใจว่าเป็นแบบพกพาหรือไม่และฉันทดสอบด้วย 'gcc-4.8.2' บน Linux
_ZTII
วิธีการเช่นtypeinfo for long
echo '_ZTIl' | c++filt
มันเป็นโครงการโกง g ++
คำถามนี้เก่ามาก แต่ฉันเพิ่งสะดุดและคิดว่าฉันจะแบ่งปันเทคนิค: หารด้วยศูนย์หรือหักล้างตัวชี้โมฆะ
คำถามคือ "วิธีขว้าง" ไม่ใช่วิธีจับหรือแม้กระทั่งวิธีการโยนข้อยกเว้นบางประเภท ฉันมีสถานการณ์เมื่อนานมาแล้วที่เราจำเป็นต้องเรียกใช้ข้อยกเว้นจาก C เพื่อให้ถูกจับใน C ++ โดยเฉพาะอย่างยิ่งเรามีรายงานข้อผิดพลาด "pure virtual function call" เป็นครั้งคราวและจำเป็นต้องโน้มน้าวให้ฟังก์ชัน _purecall ของ C runtime โยนบางสิ่ง ดังนั้นเราจึงเพิ่มฟังก์ชัน _purecall ของเราเองซึ่งหารด้วยศูนย์และบูมเราได้รับข้อยกเว้นที่เราสามารถจับ C ++ ได้และยังใช้สแต็คสนุก ๆ เพื่อดูว่ามีอะไรผิดพลาดบ้าง
ใน Win with MSVCมี__try ... __except ...
แต่มันแย่มากและคุณไม่ต้องการใช้มันหากคุณสามารถหลีกเลี่ยงได้ ดีกว่าที่จะบอกว่าไม่มีข้อยกเว้น
C ไม่มีข้อยกเว้น
มีการใช้งานแฮ็กกี้หลายแบบที่พยายามทำ (ตัวอย่างหนึ่งที่: http://adomas.org/excc/ )
ดังที่กล่าวไว้ในเธรดจำนวนมากวิธีการ "มาตรฐาน" คือการใช้ setjmp / longjmp ฉันโพสต์วิธีแก้ปัญหาดังกล่าวไปที่https://github.com/psevon/exceptions-and-raii-in-c นี่คือความรู้ของฉันวิธีแก้ปัญหาเดียวที่อาศัยการล้างทรัพยากรที่จัดสรรโดยอัตโนมัติ มันใช้สมาร์ทพอยน์เตอร์ที่ไม่ซ้ำใครและใช้ร่วมกันและอนุญาตให้ฟังก์ชันระดับกลางปล่อยให้ข้อยกเว้นผ่านไปโดยไม่ต้องจับและยังคงมีการจัดสรรทรัพยากรในพื้นที่อย่างถูกต้อง
C ไม่รองรับข้อยกเว้น คุณสามารถลองรวบรวมรหัส C ของคุณเป็น C ++ ด้วย Visual Studio หรือ G ++ และดูว่าจะรวบรวมตามที่เป็นอยู่หรือไม่ แอปพลิเคชัน C ส่วนใหญ่จะรวบรวมเป็น C ++ โดยไม่มีการเปลี่ยนแปลงที่สำคัญจากนั้นคุณสามารถใช้ไวยากรณ์ try ... catch
หากคุณเขียนโค้ดด้วยรูปแบบการออกแบบ Happy path (เช่นสำหรับอุปกรณ์ฝังตัว) คุณอาจจำลองการประมวลผลข้อผิดพลาดข้อยกเว้น (aka deffering หรือการจำลองในที่สุด) ด้วยตัวดำเนินการ "goto"
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;
}
มันไม่ได้เป็นตัวจัดการข้อยกเว้น แต่จะนำคุณไปสู่วิธีจัดการกับข้อผิดพลาดที่ทางออก fucntion
ป.ล. คุณควรระมัดระวังในการใช้ goto จากขอบเขตที่ลึกเท่ากันหรือมากกว่าเท่านั้นและห้ามข้ามการประกาศตัวแปร
การใช้ข้อยกเว้นใน cโดยEric Roberts
บทที่ 4 ของC อินเทอร์เฟซและการใช้งานโดยแฮนสัน
วินัยในการจัดการข้อผิดพลาดโดย Doug Moen
การใช้ข้อยกเว้นใน C (รายละเอียดบทความของ E Roberts)