Runtime: Pengecualian melalui PINvoke

Dibuat pada 26 Jul 2017  ·  3Komentar  ·  Sumber: dotnet/runtime

Saya sedang menguji kode berikut.

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("libupcall.so")]
    public static extern void register_callback(Callback cb);

    [DllImport("libupcall.so")]
    public static extern void upcall();

    public static void MyStaticCallback(int val)
    {
        throw new Exception("error");
    }

    public delegate void Callback(int var);
    static Callback cbMyStaticCallback = MyStaticCallback;  

    static void Main(string[] args)
    {
        try {
            register_callback(MyStaticCallback); 
            upcall();                

        } catch (Exception e) {
            Console.WriteLine("Catch clause caught : {0} \n", e.Message);
        }
    }
}

libupcall.so didasarkan pada kode sumber C berikut:

#include <stdio.h>

typedef void (*callback)(int val);

callback gCB;

extern void register_callback(callback cb)
{
    printf("register_callback:%p ----\n", (void *)cb);
    gCB = cb;
}
extern void upcall()
{
    static int c = 0;
    printf("upcall ----\n");
    gCB(c++);
}

dotnet run keluar dengan pengecualian yang tidak tertangani sebagai berikut.

twoflower@js2-desktop:~/dev/complexexception$ sudo dotnet run
register_callback:0x7f3a041f407c ----
upcall ----

Unhandled Exception: System.Exception: error
   at Program.MyStaticCallback(Int32 val) in /home/twoflower/dev/complexexception/Program.cs:line 14
   at Program.upcall()
   at Program.Main(String[] args) in /home/twoflower/dev/complexexception/Program.cs:line 24
twoflower@js2-desktop:~/dev/complexexception$ 

di sini adalah corefile bt.

* thread dotnet/coreclr#1: tid = 0, 0x00007fda93b26428 libc.so.6`__GI_raise(sig=6) + 56 at raise.c:54, name = 'dotnet', stop reason = signal SIGABRT
  * frame #0: 0x00007fda93b26428 libc.so.6`__GI_raise(sig=6) + 56 at raise.c:54
    frame dotnet/coreclr#1: 0x00007fda93b2802a libc.so.6`__GI_abort + 362 at abort.c:89
    frame dotnet/coreclr#2: 0x00007fda9326258c libcoreclr.so`??? + 124
    frame dotnet/coreclr#3: 0x00007fda9326148b libcoreclr.so`??? + 235
    frame dotnet/coreclr#4: 0x00007fda92f0b893 libcoreclr.so`??? + 531
    frame dotnet/coreclr#5: 0x00007fda92f0cd71 libcoreclr.so`??? + 593
    frame dotnet/coreclr#6: 0x00007fda92fcaae3 libcoreclr.so`??? + 51
    frame dotnet/coreclr#7: 0x00007fda93ecb263 libgcc_s.so.1`_Unwind_RaiseException(exc=0x0000000002467530) + 115 at unwind.inc:113
    frame dotnet/coreclr#8: 0x00007fda9446790c libstdc++.so.6`__cxa_throw + 92
    frame dotnet/coreclr#9: 0x00007fda9322749d libcoreclr.so`??? + 77
    frame dotnet/coreclr#10: 0x00007fda92fd781e libcoreclr.so`??? + 273
    frame dotnet/coreclr#11: 0x00007fda88e4b7b2 libupcall.so`upcall + 45 at upcall.c:16
    frame dotnet/coreclr#12: 0x00007fda19d85ae6
    frame dotnet/coreclr#13: 0x00007fda19d8588e
    frame dotnet/coreclr#14: 0x00007fda92fd67b7 libcoreclr.so`??? + 124
    frame dotnet/coreclr#15: 0x00007fda92eec630 libcoreclr.so`??? + 1264

Apakah ini perilaku normal yang menangkap blok pada fungsi Utama tidak menangkap pengecualian?

Komentar yang paling membantu

Salah satu alasannya adalah kami tidak benar-benar tahu cara menyebarkan pengecualian melalui kode asli yang disebut panggilan balik terkelola karena kami tidak tahu jenis kode apa itu. Bisa saja kode C, kode C++, kode ASM atau bahkan kode bahasa lainnya. Jika kita melewatkan frame tersebut dan itu misalnya C++, kita tidak akan memanggil destruktor objek tumpukan, sehingga mungkin membocorkan memori atau mengabaikan kunci yang terkunci dll. Jika kita mencoba untuk membuang beberapa pengecualian C++ yang telah ditentukan sebelumnya, kode asli dapat menelannya secara tidak sengaja. Atau bahkan dapat merusak beberapa runtime yang tidak siap untuk memproses pengecualian.

Semua 3 komentar

Persimpangan pengecualian berhasil ke batas asli (seperti dalam kasus Anda ketika panggilan balik dipanggil dari kode asli dan itu melempar pengecualian) sengaja tidak didukung pada inti dotnet. Anda harus menangkap semua pengecualian dalam panggilan balik yang Anda panggil dari kode asli.

Salah satu alasannya adalah kami tidak benar-benar tahu cara menyebarkan pengecualian melalui kode asli yang disebut panggilan balik terkelola karena kami tidak tahu jenis kode apa itu. Bisa saja kode C, kode C++, kode ASM atau bahkan kode bahasa lainnya. Jika kita melewatkan frame tersebut dan itu misalnya C++, kita tidak akan memanggil destruktor objek tumpukan, sehingga mungkin membocorkan memori atau mengabaikan kunci yang terkunci dll. Jika kita mencoba untuk membuang beberapa pengecualian C++ yang telah ditentukan sebelumnya, kode asli dapat menelannya secara tidak sengaja. Atau bahkan dapat merusak beberapa runtime yang tidak siap untuk memproses pengecualian.

Terima kasih banyak.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

GitAntoinee picture GitAntoinee  ·  3Komentar

matty-hall picture matty-hall  ·  3Komentar

noahfalk picture noahfalk  ·  3Komentar

nalywa picture nalywa  ·  3Komentar

omajid picture omajid  ·  3Komentar