web-dev-qa-db-ja.com

Cで例外をスローする方法は?

これをgoogleに入力しましたが、C++のハウツーしか見つかりませんでした。

cでそれを行う方法は?

82
httpinterpret

Cには例外はありません。Cでは、エラーは、関数の戻り値、プロセスの終了値、プロセスへのシグナル( Program Error Signals(GNU libc) )またはCPUによって通知されますハードウェア割り込み(またはCPUからのその他の通知エラーがある場合)( ゼロによる除算の場合のプロセッサの処理方法 )。

ただし、C++およびその他の言語で定義された例外。 C++での例外処理は、C++標準「S.15例外処理」で指定されており、C標準には同等のセクションはありません。

64
Brian R. Bondy

Cでは、_setjmp.h_で定義されているsetjmp()関数とlongjmp()関数の組み合わせを使用できます。 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;
}
_

注:実際にそれらを使用することをお勧めしますnot C++ではひどい(ローカルオブジェクトのデストラクタは呼び出されない)、何が起こっているのかを理解するのは本当に難しい。代わりに何らかのエラーを返します。

29
vava

プレーンオールドCは、実際にはネイティブで例外をサポートしていません。

次のような代替エラー処理戦略を使用できます。

  • エラーコードを返す
  • FALSEを返し、last_error変数または関数。

http://en.wikibooks.org/wiki/C_Programming/Error_handling を参照してください。

18
Lucas Jones

Cにはbuilt-in例外メカニズムはありません。例外とそのセマンティクスをsimulateする必要があります。これは通常、setjmpおよびlongjmpに依存することで実現されます。

周りにはかなりの数のライブラリがあり、私はさらに別のライブラリを実装しています。 exceptions4c ;と呼ばれます。ポータブルで無料です。あなたはそれを見て、 他の選択肢 と比較して、どれがあなたに最も合うかを見ることができます。

17
Guillermo Calvo

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

ポータブルかどうかはわかりませんが、Linuxで「gcc-4.8.2」でテストします。

9
wcy

Winで[〜#〜] msvc [〜#〜]があります__try ... __except ...しかし、それは本当に恐ろしいものであり、あなたがそれを避けることができるなら、あなたはそれを使いたくない。例外はないと言っておくといいでしょう。

7
Donal Fellows

この質問は非常に古いものですが、私はそれを偶然見つけて、ゼロで除算するか、nullポインターを逆参照するというテクニックを共有すると思いました。

問題は単に「投げる方法」であり、キャッチする方法ではなく、特定のタイプの例外をスローする方法です。何年も前に、Cから例外をトリガーしてC++でキャッチする必要がある状況がありました。具体的には、「純粋な仮想関数呼び出し」エラーのレポートがときどきあり、Cランタイムの_purecall関数に何かをスローさせるように説得する必要がありました。そこで、ゼロで割った独自の_purecall関数とブームを追加しました。C++でキャッチできる例外が発生し、スタックの楽しみを使ってどこがうまくいかなかったかを確認することさえできました。

7
Joe

Cには例外はありません。

それを実行しようとするさまざまな実装があります(例: http://adomas.org/excc/ )。

6
Joe

多数のスレッドで述べたように、これを行う「標準的な」方法はsetjmp/longjmpを使用することです。 https://github.com/psevon/exceptions-and-raii-in-c にこのようなソリューションをもう1つ投稿しました。これは、割り当てられたリソースの自動クリーンアップに依存する唯一のソリューションです。一意の共有スマートポインタを実装し、中間関数が例外をキャッチせずに通過させ、ローカルに割り当てられたリソースを適切にクリーンアップできるようにします。

3
user3510229

Cは例外をサポートしていません。 Visual StudioまたはG ++でCコードをC++としてコンパイルして、そのままコンパイルできるかどうかを確認できます。ほとんどのCアプリケーションは、大きな変更なしでC++としてコンパイルされ、try ... catch構文を使用できます。

2

ハッピーパスデザインパターン(つまり、組み込みデバイス用)でコードを記述する場合、演算子「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;
}

実際には例外ハンドラーではありませんが、機能終了時にエラーを処理する方法があります。

追伸gotoは同じスコープまたはより深いスコープからのみ慎重に使用し、変数宣言をジャンプしないでください。

0
Vitold S.