Saya mengetik ini ke google tetapi hanya menemukan howtos di C ++,
bagaimana melakukannya di C?
Saya mengetik ini ke google tetapi hanya menemukan howtos di C ++,
bagaimana melakukannya di C?
Jawaban:
Tidak ada pengecualian di C. Dalam C kesalahan diberitahukan oleh nilai yang dikembalikan dari fungsi, nilai keluar dari proses, sinyal ke proses ( Program Error Signals (GNU libc) ) atau gangguan perangkat keras CPU (atau pemberitahuan lainnya kesalahan bentuk CPU jika ada) ( Bagaimana prosesor menangani kasus pembagian dengan nol ).
Pengecualian didefinisikan dalam C ++ dan bahasa lain. Penanganan pengecualian di C ++ ditentukan dalam standar C ++ "Penanganan pengecualian S.15", tidak ada bagian yang setara dalam standar C.
main
di .c
file yang dapat mencakup beberapa C ++, dan karena itu pengecualian bisa dilemparkan dan tertangkap dalam program ini, tetapi bagian-bagian kode C akan tetap tahu tentang semua ini terjadi kecuali bahwa pengecualian melempar dan menangkap sering mengandalkan fungsi ditulis dalam C yang berada di pustaka C ++. C digunakan karena Anda tidak dapat mengambil risiko fungsi yang dipanggil untuk melakukan throw
pengecualian itu sendiri. Mungkin ada cara spesifik compiler / library / target untuk melempar / menangkap pengecualian. Tapi melempar instance kelas akan memiliki masalahnya sendiri.
Di C Anda bisa menggunakan kombinasi dari setjmp()
dan longjmp()
fungsi, yang didefinisikan di setjmp.h
. Contoh dari 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;
}
Catatan: Saya benar-benar menyarankan Anda untuk tidak menggunakannya karena mereka bekerja buruk dengan C ++ (penghancur objek lokal tidak akan dipanggil) dan sangat sulit untuk memahami apa yang sedang terjadi. Kembalikan beberapa jenis kesalahan sebagai gantinya.
if()
. Saya tidak bisa melihat bahaya di dalamnya; bisakah orang lain disini?
C lama biasa sebenarnya tidak mendukung pengecualian secara native.
Anda dapat menggunakan strategi penanganan kesalahan alternatif, seperti:
FALSE
dan menggunakan last_error
variabel atau fungsi.Lihat http://en.wikibooks.org/wiki/C_Programming/Error_handling .
GetLastError()
di windows API.
Ada tidak ada built-in mekanisme pengecualian dalam C; Anda perlu menyimulasikan pengecualian dan semantiknya. Ini biasanya dicapai dengan mengandalkan setjmp
dan longjmp
.
Ada cukup banyak perpustakaan di sekitar, dan saya sedang mengimplementasikan yang lain. Ini disebut exceptionions4c ; portabel dan gratis. Anda dapat melihatnya, dan membandingkannya dengan alternatif lain untuk melihat mana yang paling cocok untuk Anda.
C dapat menampilkan pengecualian C ++, mereka tetap kode mesin. Misalnya, di 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
di 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;
}
untuk menyusunnya
gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out
keluaran
good 1976
http://mentorembedded.github.io/cxx-abi/abi-eh.html memiliki info lebih detail tentang __cxa_throw
.
Saya tidak yakin apakah ini portabel atau tidak, dan saya mengujinya dengan 'gcc-4.8.2' di Linux.
_ZTII
artinya typeinfo for long
, mis echo '_ZTIl' | c++filt
. Ini adalah skema mangling g ++.
Pertanyaan ini sangat tua, tetapi saya baru saja menemukan itu dan berpikir saya akan berbagi teknik: bagi dengan nol, atau dereferensi penunjuk nol.
Pertanyaannya hanyalah "bagaimana cara melempar", bukan bagaimana cara menangkap, atau bahkan bagaimana cara melempar jenis pengecualian tertentu. Saya memiliki situasi berabad-abad yang lalu di mana kami perlu memicu pengecualian dari C untuk ditangkap di C ++. Secara khusus, kami memiliki laporan sesekali tentang kesalahan "panggilan fungsi virtual murni", dan perlu meyakinkan fungsi _purecall runtime C untuk melempar sesuatu. Jadi kami menambahkan fungsi _purecall kami sendiri yang dibagi dengan nol, dan boom, kami mendapat pengecualian yang dapat kami tangkap di C ++, dan bahkan menggunakan beberapa stack fun untuk melihat di mana ada yang salah.
Tentang Win with MSVC ada __try ... __except ...
tetapi itu benar-benar mengerikan dan Anda tidak ingin menggunakannya jika Anda mungkin dapat menghindarinya. Lebih baik mengatakan bahwa tidak ada pengecualian.
C tidak memiliki pengecualian.
Ada berbagai implementasi hacky yang mencoba melakukannya (salah satu contohnya di: http://adomas.org/excc/ ).
Seperti disebutkan di banyak utas, cara "standar" untuk melakukan ini adalah menggunakan setjmp / longjmp. Saya memposting solusi lain seperti itu ke https://github.com/psevon/exceptions-and-raii-in-c. Sepengetahuan saya, ini adalah satu-satunya solusi yang mengandalkan pembersihan otomatis sumber daya yang dialokasikan. Ini mengimplementasikan smartpointers yang unik dan bersama, dan memungkinkan fungsi perantara untuk membiarkan pengecualian lewat tanpa menangkap dan masih memiliki sumber daya yang dialokasikan secara lokal dibersihkan dengan benar.
C tidak mendukung pengecualian. Anda dapat mencoba mengompilasi kode C Anda sebagai C ++ dengan Visual Studio atau G ++ dan melihat apakah itu akan dikompilasi sebagaimana adanya. Sebagian besar aplikasi C akan dikompilasi sebagai C ++ tanpa perubahan besar, dan Anda kemudian dapat menggunakan sintaks try ... catch.
Jika Anda menulis kode dengan pola desain Happy path (yaitu untuk perangkat tertanam) Anda dapat mensimulasikan pemrosesan kesalahan pengecualian (alias menunda atau akhirnya emulasi) dengan operator "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;
}
Ini tidak benar-benar pengecualian penangan tetapi itu membawa Anda cara untuk menangani kesalahan saat keluar dari fucntion.
PS Anda harus berhati-hati menggunakan goto hanya dari cakupan yang sama atau lebih dalam dan tidak pernah melompati deklarasi variabel.