Bunu google'a yazdım ama sadece C ++ 'da howtos buldum,
C'de nasıl yapılır?
Bunu google'a yazdım ama sadece C ++ 'da howtos buldum,
C'de nasıl yapılır?
Yanıtlar:
C'de istisna yoktur. C'de hatalar, işlevin döndürülen değeri, işlemin çıkış değeri, sürece gönderilen sinyaller ( Program Hata Sinyalleri (GNU libc) ) veya CPU donanım kesintisi (veya diğer bildirimler) ile bildirilir. varsa CPU hatası) ( İşlemci sıfıra bölme durumunu nasıl ele alır ).
İstisnalar C ++ ve diğer dillerde tanımlanmıştır. C ++ 'da özel durum işleme, C ++ standardı "S.15 İstisna işleme" içinde belirtilmiştir, C standardında eşdeğer bir bölüm yoktur.
main
bulunan bir program .c
, bazı C ++ içerebilir ve bu nedenle istisnalar programa atılabilir ve yakalanabilir, ancak C kodu bölümleri, istisna atma ve yakalama genellikle C ile yazılmış işlevlere bağlı olması dışında, tüm bunlardan habersiz kalacaktır. C ++ kitaplıklarında bulunur. C kullanılır, çünkü çağrılan işlevin throw
kendisine bir istisna atma ihtiyacı duyma riskini alamazsınız . Yine de, istisnaları atmanın / yakalamanın özel bir yolu olabilir. Ancak bir sınıf örneği atmanın kendi sorunları olacaktır.
C'de tanımlanan setjmp()
ve longjmp()
işlevlerinin kombinasyonunu kullanabilirsiniz setjmp.h
. Wikipedia'dan örnek
#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;
}
Not: Aslında tavsiye ederiz değil onlar C korkunç çalışırken bunları kullanmak için ++ (yerel nesnelerin yıkıcılar denilen olsun olmazdı) ve ne olup bittiğini anlamak gerçekten zor. Bunun yerine bir tür hata döndür.
if()
. İçinde bir tehlike göremiyorum; burada başka biri olabilir mi?
Düz eski C aslında istisnaları yerel olarak desteklemez.
Aşağıdakiler gibi alternatif hata işleme stratejileri kullanabilirsiniz:
FALSE
bir last_error
değişken veya işlevi döndürme ve kullanma .Bkz. Http://en.wikibooks.org/wiki/C_Programming/Error_handling .
GetLastError()
Windows API'de.
C'de yerleşik bir istisna mekanizması yoktur ; istisnaları ve anlamlarını simüle etmeniz gerekir . Bu genellikle setjmp
ve güvenerek elde edilir longjmp
.
Etrafta epeyce kütüphane var ve bir tane daha uyguluyorum. Buna istisnalar4c denir ; taşınabilir ve ücretsizdir. Hangisinin size en uygun olduğunu görmek için ona bir göz atabilir ve diğer alternatiflerle karşılaştırabilirsiniz .
C, C ++ istisnası atabilir, bunlar zaten makine kodlarıdır. Örneğin, bar.c içinde
// 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 içinde
#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;
}
derlemek için
gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out
çıktı
good 1976
http://mentorembedded.github.io/cxx-abi/abi-eh.html hakkında daha ayrıntılı bilgi var __cxa_throw
.
Taşınabilir olup olmadığından emin değilim ve Linux'ta 'gcc-4.8.2' ile test ediyorum.
_ZTII
anlamına gelir typeinfo for long
, örn echo '_ZTIl' | c++filt
. Bu, g ++ değiştirme şemasıdır.
Bu soru çok eski, ama ben sadece ona rastladım ve bir tekniği paylaşacağımı düşündüm: sıfıra bölmek veya boş göstericiyi referans almak.
Soru basitçe "nasıl fırlatılır", nasıl yakalanacağı, hatta belirli bir istisna türünün nasıl atılacağı değil. C ++ 'da yakalanmak için C'den bir istisnayı tetiklememiz gereken yıllar önce bir durum yaşadım. Özellikle, "saf sanal işlev çağrısı" hatalarıyla ilgili ara sıra raporlar aldık ve C çalışma zamanının _purecall işlevini bir şeyler atmaya ikna etmemiz gerekiyordu. Böylece sıfıra bölünen kendi _purecall işlevimizi ekledik ve patlama, C ++ 'da yakalayabileceğimiz bir istisna var ve hatta işlerin nerede ters gittiğini görmek için biraz yığın eğlencesi kullanıyoruz.
MSVC ile Win'de var __try ... __except ...
ama bu gerçekten korkunç ve eğer bundan kaçınabiliyorsanız kullanmak istemezsiniz. İstisnaların olmadığını söylemek daha iyi.
C'nin istisnaları yoktur.
Bunu yapmaya çalışan çeşitli hacky uygulamaları vardır (bir örnek: http://adomas.org/excc/ ).
Birçok iş parçacığında bahsedildiği gibi, bunu yapmanın "standart" yolu setjmp / longjmp kullanmaktır. Https://github.com/psevon/exceptions-and-raii-in-c adresinde böyle bir başka çözüm daha yayınladım. Bu, tahsis edilen kaynakların otomatik olarak temizlenmesine dayanan bildiğim tek çözümdür. Eşsiz ve paylaşılan akıllı işaretçiler uygular ve ara işlevlerin istisnaların yakalanmadan geçmesine ve yerel olarak tahsis edilen kaynaklarının düzgün bir şekilde temizlenmesine izin vermesine izin verir.
C istisnaları desteklemez. C kodunuzu Visual Studio veya G ++ ile C ++ olarak derlemeyi deneyebilir ve olduğu gibi derlenip derlenmeyeceğini görebilirsiniz. Çoğu C uygulaması, büyük değişiklikler olmadan C ++ olarak derlenir ve ardından try ... catch sözdizimini kullanabilirsiniz.
Mutlu yol tasarım deseniyle (yani gömülü aygıt için) kod yazarsanız, "goto" operatörüyle istisna hatası işlemeyi (diğer bir deyişle, deffering veya son olarak emülasyon) simüle edebilirsiniz.
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;
}
Aslında istisna işleyici değildir, ancak fucntion çıkışındaki hatayı ele almanın bir yolunu alır.
Not: Dikkatli olmalısınız, sadece aynı veya daha fazla derin kapsamdan gidin ve değişken bildirimini asla atlamayın.
Eric Roberts tarafından c'de istisnaların uygulanması
C Arayüzleri ve Uygulamaları , Bölüm 4, Hanson.
Doug Moen'den Hata Giderme Disiplini
C'de İstisnaların Uygulanması (E Roberts'ın makalesinin ayrıntıları)