Contoh
int *ptr;
*ptr = 1000;
dapatkah saya menangkap pengecualian pelanggaran akses memori menggunakan standar C ++ tanpa menggunakan microsoft tertentu.
Contoh
int *ptr;
*ptr = 1000;
dapatkah saya menangkap pengecualian pelanggaran akses memori menggunakan standar C ++ tanpa menggunakan microsoft tertentu.
Jawaban:
Nggak. C ++ tidak mengeluarkan pengecualian saat Anda melakukan sesuatu yang buruk, yang akan mengakibatkan kinerja yang buruk. Hal-hal seperti pelanggaran akses atau kesalahan pembagian dengan nol lebih seperti pengecualian "mesin", daripada hal-hal tingkat bahasa yang dapat Anda tangkap.
Bacalah dan menangislah!
Saya menemukan jawabannya. Jika anda tidak melempar dari pawang, pawang hanya akan melanjutkan dan begitu juga dengan pengecualiannya.
Keajaiban terjadi ketika Anda melemparkan pengecualian Anda sendiri dan menanganinya.
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <tchar.h>
void SignalHandler(int signal)
{
printf("Signal %d",signal);
throw "!Access Violation!";
}
int main()
{
typedef void (*SignalHandlerPointer)(int);
SignalHandlerPointer previousHandler;
previousHandler = signal(SIGSEGV , SignalHandler);
try{
*(int *) 0 = 0;// Baaaaaaad thing that should never be caught. You should write good code in the first place.
}
catch(char *e)
{
printf("Exception Caught: %s\n",e);
}
printf("Now we continue, unhindered, like the abomination never happened. (I am an EVIL genius)\n");
printf("But please kids, DONT TRY THIS AT HOME ;)\n");
}
sigaltstack
) yang dipasang (kecuali implementasi pelepasan pengecualian C ++ memungkinkannya), dan setiap fungsi runtime yang menangani mekanisme pelepasan itu sendiri harus aman terhadap sinyal.
signal(SIGSEGV, SIG_DFL);
Ada cara yang sangat mudah untuk menangkap segala jenis pengecualian (pembagian dengan nol, pelanggaran akses, dll.) Di Visual Studio menggunakan blok try -> catch (...). Pengaturan proyek kecil sudah cukup. Cukup aktifkan / EHa opsi di pengaturan proyek. Lihat Properti Proyek -> C / C ++ -> Pembuatan Kode -> Ubah Pengecualian Aktifkan C ++ menjadi "Ya Dengan Pengecualian SEH" . Itu dia!
Lihat detailnya di sini: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
Setidaknya bagi saya, signal(SIGSEGV ...)
pendekatan yang disebutkan dalam jawaban lain tidak berfungsi pada Win32 dengan Visual C ++ 2015 . Apa yang melakukan pekerjaan untuk saya adalah untuk menggunakan _set_se_translator()
ditemukan di eh.h
. Ini bekerja seperti ini:
Langkah 1 ) Pastikan Anda mengaktifkan Ya dengan Pengecualian SEH (/ EHa) di Properti Proyek / C ++ / Pembuatan Kode / Aktifkan Pengecualian C ++ , seperti yang disebutkan dalam jawaban oleh Volodymyr Frytskyy .
Langkah 2 ) Panggil _set_se_translator()
, berikan penunjuk fungsi (atau lambda) untuk penerjemah pengecualian baru . Ini disebut penerjemah karena pada dasarnya hanya mengambil pengecualian tingkat rendah dan melemparkannya kembali sebagai sesuatu yang lebih mudah ditangkap, seperti std::exception
:
#include <string>
#include <eh.h>
// Be sure to enable "Yes with SEH Exceptions (/EHa)" in C++ / Code Generation;
_set_se_translator([](unsigned int u, EXCEPTION_POINTERS *pExp) {
std::string error = "SE Exception: ";
switch (u) {
case 0xC0000005:
error += "Access Violation";
break;
default:
char result[11];
sprintf_s(result, 11, "0x%08X", u);
error += result;
};
throw std::exception(error.c_str());
});
Langkah 3 ) Tangkap pengecualian seperti biasa:
try{
MakeAnException();
}
catch(std::exception ex){
HandleIt();
};
Jenis situasi ini bergantung pada implementasi dan akibatnya akan membutuhkan mekanisme khusus vendor untuk menjebak. Dengan Microsoft ini akan melibatkan SEH, dan * nix akan melibatkan sinyal
Secara umum, meskipun menangkap pengecualian Pelanggaran Akses adalah ide yang sangat buruk. Hampir tidak ada cara untuk memulihkan dari pengecualian AV dan mencoba melakukannya hanya akan semakin sulit menemukan bug dalam program Anda.
Seperti yang dinyatakan, tidak ada cara vendor non Microsoft / compiler untuk melakukan ini di platform windows. Namun, jelas berguna untuk menangkap jenis pengecualian ini dengan cara try {} catch (exception ex) {} normal untuk pelaporan kesalahan dan lebih banyak lagi jalan keluar yang anggun dari aplikasi Anda (seperti yang dikatakan JaredPar, aplikasi sekarang mungkin dalam masalah) . Kami menggunakan _se_translator_function dalam pembungkus kelas sederhana yang memungkinkan kita untuk menangkap pengecualian berikut dalam penangan percobaan:
DECLARE_EXCEPTION_CLASS(datatype_misalignment)
DECLARE_EXCEPTION_CLASS(breakpoint)
DECLARE_EXCEPTION_CLASS(single_step)
DECLARE_EXCEPTION_CLASS(array_bounds_exceeded)
DECLARE_EXCEPTION_CLASS(flt_denormal_operand)
DECLARE_EXCEPTION_CLASS(flt_divide_by_zero)
DECLARE_EXCEPTION_CLASS(flt_inexact_result)
DECLARE_EXCEPTION_CLASS(flt_invalid_operation)
DECLARE_EXCEPTION_CLASS(flt_overflow)
DECLARE_EXCEPTION_CLASS(flt_stack_check)
DECLARE_EXCEPTION_CLASS(flt_underflow)
DECLARE_EXCEPTION_CLASS(int_divide_by_zero)
DECLARE_EXCEPTION_CLASS(int_overflow)
DECLARE_EXCEPTION_CLASS(priv_instruction)
DECLARE_EXCEPTION_CLASS(in_page_error)
DECLARE_EXCEPTION_CLASS(illegal_instruction)
DECLARE_EXCEPTION_CLASS(noncontinuable_exception)
DECLARE_EXCEPTION_CLASS(stack_overflow)
DECLARE_EXCEPTION_CLASS(invalid_disposition)
DECLARE_EXCEPTION_CLASS(guard_page)
DECLARE_EXCEPTION_CLASS(invalid_handle)
DECLARE_EXCEPTION_CLASS(microsoft_cpp)
Kelas asli berasal dari artikel yang sangat berguna ini:
Bukan mekanisme penanganan pengecualian, tetapi Anda dapat menggunakan mekanisme signal () yang disediakan oleh C.
> man signal
11 SIGSEGV create core image segmentation violation
Menulis ke pointer NULL mungkin akan menyebabkan sinyal SIGSEGV
signal()
adalah bagian dari standar posix . Windows mengimplementasikan standar posix (seperti halnya Linux dan unix)
Pelanggaran seperti itu berarti ada yang salah dengan kode, dan tidak dapat diandalkan. Saya dapat melihat bahwa sebuah program mungkin ingin mencoba untuk menyimpan data pengguna dengan cara yang diharapkan tidak akan menimpa data sebelumnya, dengan harapan bahwa data pengguna belum rusak, tetapi menurut definisi tidak ada metode standar menangani perilaku tidak terdefinisi.