ตัวอย่าง
int *ptr;
*ptr = 1000;
ฉันสามารถตรวจจับข้อยกเว้นการละเมิดการเข้าถึงหน่วยความจำโดยใช้ C ++ มาตรฐานโดยไม่ต้องใช้ไมโครซอฟท์โดยเฉพาะ
ตัวอย่าง
int *ptr;
*ptr = 1000;
ฉันสามารถตรวจจับข้อยกเว้นการละเมิดการเข้าถึงหน่วยความจำโดยใช้ C ++ มาตรฐานโดยไม่ต้องใช้ไมโครซอฟท์โดยเฉพาะ
คำตอบ:
ไม่ C ++ ไม่ทำให้เกิดข้อยกเว้นเมื่อคุณทำสิ่งที่ไม่ดีซึ่งจะทำให้เกิดผลกระทบด้านประสิทธิภาพ สิ่งต่างๆเช่นการละเมิดการเข้าถึงหรือการหารด้วยข้อผิดพลาดเป็นศูนย์นั้นเหมือนกับข้อยกเว้น "เครื่อง" มากกว่าสิ่งที่เป็นระดับภาษาที่คุณสามารถจับได้
อ่านแล้วจะร้องไห้!
ฉันคิดออกแล้ว หากคุณไม่โยนออกจากตัวจัดการตัวจัดการก็จะดำเนินการต่อและข้อยกเว้นก็เช่นกัน
เวทมนตร์เกิดขึ้นเมื่อคุณโยนข้อยกเว้นและจัดการกับสิ่งนั้น
#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
ติดตั้งสแต็กสัญญาณอื่น ๆ ( ) (เว้นแต่ว่าข้อยกเว้น C ++ จะอนุญาตให้ใช้งานได้) และทุกฟังก์ชันรันไทม์ที่จัดการกลไกการคลายตัวเองควรมีความปลอดภัยของสัญญาณ
signal(SIGSEGV, SIG_DFL);
มีวิธีที่ง่ายมากในการตรวจจับข้อยกเว้นใด ๆ (การหารด้วยศูนย์การละเมิดการเข้าถึง ฯลฯ ) ในVisual Studioโดยใช้บล็อก try -> catch (... ) การปรับแต่งการตั้งค่าโครงการเล็กน้อยก็เพียงพอแล้ว เพียงแค่เปิดใช้งาน / EHa ตัวเลือกในการตั้งค่าโครงการ ดูคุณสมบัติโครงการ -> C / C ++ -> การสร้างโค้ด -> แก้ไขการเปิดใช้งานข้อยกเว้น C ++ เป็น "ใช่ด้วยข้อยกเว้น SEH"SEH" แค่นั้นแหละ!
ดูรายละเอียดที่นี่: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
อย่างน้อยสำหรับฉันที่signal(SIGSEGV ...)
วิธีการที่กล่าวถึงในคำตอบอื่นไม่ได้ทำงานใน Win32 ด้วย Visual C ++ 2015 สิ่งที่ได้ผลสำหรับฉันคือการใช้ที่_set_se_translator()
พบในeh.h
. มันทำงานดังนี้:
ขั้นตอนที่ 1 ) ตรวจสอบให้แน่ใจว่าคุณเปิดใช้งานใช่ด้วยข้อยกเว้น SEH (/ EHa)ในคุณสมบัติโครงการ / C ++ / การสร้างรหัส / เปิดใช้งานข้อยกเว้น C ++ดังที่กล่าวไว้ในคำตอบของVolodymyr FrytskyyFrytskyy
ขั้นตอนที่ 2 ) โทร_set_se_translator()
ผ่านในตัวชี้ฟังก์ชัน (หรือแลมบ์ดา) สำหรับข้อยกเว้นใหม่แปล เรียกว่านักแปลเพราะโดยพื้นฐานแล้วใช้ข้อยกเว้นระดับต่ำและโยนใหม่เป็นสิ่งที่ง่ายต่อการจับเช่น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());
});
ขั้นตอนที่ 3 ) ตรวจจับข้อยกเว้นเหมือนที่คุณทำตามปกติ:
try{
MakeAnException();
}
catch(std::exception ex){
HandleIt();
};
สถานการณ์ประเภทนี้ขึ้นอยู่กับการนำไปใช้งานและด้วยเหตุนี้จึงต้องใช้กลไกเฉพาะของผู้ขายเพื่อดักจับ สำหรับ Microsoft สิ่งนี้จะเกี่ยวข้องกับ SEH และ * nix จะเกี่ยวข้องกับสัญญาณ
โดยทั่วไปแม้ว่าการตรวจจับข้อยกเว้นการละเมิดการเข้าถึงจะเป็นไฟล์ ความคิดที่แย่มาก แทบไม่มีวิธีใดเลยที่จะกู้คืนจากข้อยกเว้น AV และการพยายามทำเช่นนั้นจะทำให้พบจุดบกพร่องในโปรแกรมของคุณได้ยากขึ้น
ตามที่ระบุไว้ไม่มีวิธีของผู้จำหน่ายที่ไม่ใช่ Microsoft / คอมไพเลอร์ในการดำเนินการนี้บนแพลตฟอร์ม windows อย่างไรก็ตามเห็นได้ชัดว่ามีประโยชน์ในการตรวจจับข้อยกเว้นประเภทนี้ในวิธีการลองใช้ {} catch (ข้อยกเว้น ex) {} ปกติสำหรับการรายงานข้อผิดพลาดและวิธีการออกจากแอปของคุณอย่างสง่างาม (ดังที่ JaredPar กล่าวว่าแอปอาจมีปัญหา) . เราใช้ _se_translator_function ใน class wrapper ที่ช่วยให้เราสามารถจับข้อยกเว้นต่อไปนี้ในตัวจัดการลอง:
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)
คลาสดั้งเดิมมาจากบทความที่มีประโยชน์มากนี้:
ไม่ใช่กลไกการจัดการข้อยกเว้น แต่คุณสามารถใช้กลไกสัญญาณ () ที่จัดทำโดย C.
> man signal
11 SIGSEGV create core image segmentation violation
การเขียนไปยังตัวชี้ NULL อาจทำให้เกิดสัญญาณ SIGSEGV
signal()
เป็นส่วนหนึ่งของมาตรฐาน posix Windows ใช้มาตรฐาน posix (เช่นเดียวกับ Linux และ unix)
การละเมิดดังกล่าวหมายความว่ามีบางอย่างผิดปกติอย่างร้ายแรงกับรหัสและไม่น่าเชื่อถือ ฉันเห็นว่าโปรแกรมอาจต้องการพยายามบันทึกข้อมูลของผู้ใช้ในลักษณะที่หวังว่าจะไม่เขียนทับข้อมูลก่อนหน้านี้โดยหวังว่าข้อมูลของผู้ใช้จะไม่เสียหาย แต่ไม่มีวิธีการมาตรฐานตามคำจำกัดความ ของการจัดการกับพฤติกรรมที่ไม่ได้กำหนด