سؤال

ولدي البرنامج الذي يقوم عمدا القسمة على صفر (ويخزن النتيجة في متغير متقلب) من أجل وقف في ظروف معينة. ومع ذلك، أود أن تكون قادرة على تعطيل هذا وقف، من دون تغيير الماكرو الذي يقوم بإجراء القسمة على صفر.

هل هناك أي طريقة لتجاهل ذلك؟

ولقد حاولت استخدام

#include <signal.h>
...
int main(void) {
  signal(SIGFPE, SIG_IGN);
  ...
}

ولكن لا يزال يموت مع الرسالة "باستثناء نقطة عائمة (ملقاة الأساسية)".

وأنا في الواقع لا تستخدم قيمة، لذلك لا يهمني حقا ما المسندة إلى متغير. 0، عشوائي، غير محدد ...

وتحرير: أعرف أن هذا ليس هو الأكثر المحمولة، لكنه مخصص للجهاز جزءا لا يتجزأ من الذي يعمل على العديد من أنظمة تشغيل مختلفة. العمل توقف الافتراضي هو القسمة على صفر. تتطلب منصات أخرى مختلف الحيل لفرض الناجم عن إعادة تشغيل الوكالة الدولية للطاقة (مثل حلقة لا نهائية مع المقاطعات تعطيل). لبيئة اختبار PC (لينكس)، أردت أن تعطيل وقف على القسمة على الصفر دون الاعتماد على أشياء مثل تأكيد.

هل كانت مفيدة؟

المحلول

لماذا هل تعمد إجراء القسمة على الصفر لوقف؟ لا يمكن أن exit(-1) أو بعض ما يعادلها؟

وخاصة إذا كنت لا تحتاج إلى نتيجة القسمة على 0، وهذا فقط لا معنى له.

نصائح أخرى

حسنا، أولا، يجب عليك أن تستخدم <ط> sigaction (2) بدلا من signal() إهمال.

وثانيا، وذلك باستخدام SIGFPE لأغراض إنهاء البرنامج من السخف واضح، كما يجب أن يتم رفع إشارة مثل SIGTERM أو SIGUSR1 بدلا من لجنة التحكيم، تزوير بعض الإشارات الأخرى لمن الآثار الجانبية، وتجاهل قيمته الدلالية. وبشكل أكثر تحديدا، وصفحة الرجل ل<ط> sigaction (2) لديها قسم NOTES مع دعاية مغالى فيها عن SIGFPE التي تشير إلى واحد أو اثنين طرقك الاستخدام المقصود منه هو كسر.

ما يجب عليك فعله هو <ط> رفع (3) إشارة عندما تريد إنهاء. ثم، استخدم الحقل sa_handler في بنية sigaction لتغيير ما إذا كان تجاهل (SIG_IGN) أو إنهاء (SIG_DFL) على أن الإشارة.

int main(void) {
  struct sigaction my_action;

  my_action.sa_handler = SIG_IGN;
  my_action.sa_flags = SA_RESTART;
  sigaction(SIGUSR1, &my_action, NULL);

  raise(SIGUSR1);  /* Ignored */

  my_action.sa_handler = SIG_DFL;
  sigaction(SIGUSR1, &my_action, NULL);

  raise(SIGUSR1); /* Terminates */

  return 0;
}

وقال ذلك، لا استطيع ان ارى لماذا كنت تستخدم إشارات بدلا من exit() بسيطة.

وتحقق قيمة الإرجاع

signal(SIGFPE, SIG_IGN);

إذا تحصل SIG_ERR، تحقق قيمة errno لمعرفة ما حدث من خطأ. وهذا بقدر ما يمكن القيام به تنقليا.

وأنا أعلم أنك لا تريد تغيير القسمة على الصفر، لكنه nonportable وغير متوقع. تريد coredump حالة حدوث بعض شرط، ولكن أن تكون قادرة على تعطيل هذا السلوك دون تحرير مدونة؟ استخدام assert وNDEBUG.

وهذه ليست المحمولة، ولكن على إلى x86 يمكنك من خلال السيطرة على FPU:

وعن طريق دول مجلس التعاون الخليجي على لينكس (أنا متأكد من المجمعين أخرى على مرافق مماثلة):

#include <fpu_control.h>

_FPU_SETCW (_FPU_DEFAULT);

ومنذ التخلف _FPU_DEFAULT إلى _FPU_MASK_ZM مجموعة (ZM لتقف على صفر-تقسيم-قناع).

void handler(int trapId)
{
   // Whatever
}

signal(SIGFPE, handler);

هل يمكن أن تتسبب في برنامج للخروج من خلال التعبير أقل مفتعلة؟ على سبيل المثال:

#include <signal.h>

#ifdef DEBUG
#define DIE_HERE raise(SIGFPE)
#else
#define DIE_HERE
#endif

وسأكون مترددة في تجاوز السلوك الافتراضي، لئلا أي جزء آخر من الفجوة البرنامج على صفر غير قصد. بدلا من ذلك، إذا كنت مما اضطرها للخروج بهذه الطريقة من أجل الحصول على تفريغ الأساسية، قد ترغب في النظر في استخدام نقاط ضمن المصحح. أو، إذا كنت على نظام مع المصحح جدب، قد يكون أداة مفيدة gcore.

إذا كان لديك السيطرة على رمز تحطمها، ثم أوصى أيضا لتغيير رمز للموت بطريقة أخرى. إذا لم تقم بذلك، قد تتمكن من محاولة لتثبيت معالج إشارة فارغة بدلا من ذلك (أي استخدام signal(SIGFPE, &EmptyFunction))، ولكن كنت لا تزال تعتمد على سلوك غير معرف، لذلك ليس هناك ضمان انها لا تزال تعمل على أنظمة أخرى، أو غيرها من نواة أو C إصدارات المكتبة.

وlnmiit ل على رمز تحطمها، ثم أوصى أيضا لتغيير رمز للموت بطريقة أخرى. إذا لم تقم بذلك، قد تتمكن من محاولة لتثبيت

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top