سؤال

ماذا تعني رسالة "خطأ الناقل" وكيف تختلف عن segfault؟

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

المحلول

تعد أخطاء الناقل نادرة هذه الأيام على نظام التشغيل x86 وتحدث عندما يتعذر على المعالج الخاص بك حتى محاولة الوصول إلى الذاكرة المطلوبة، عادةً:

  • استخدام تعليمات المعالج بعنوان لا يلبي متطلبات المحاذاة الخاصة به.

تحدث أخطاء التجزئة عند الوصول إلى الذاكرة التي لا تنتمي إلى العملية الخاصة بك، وهي شائعة جدًا وتكون عادةً نتيجة لما يلي:

  • باستخدام مؤشر إلى شيء تم إلغاء تخصيصه.
  • باستخدام مؤشر غير مهيأ ومن ثم زائف.
  • باستخدام مؤشر فارغ.
  • تفيض المخزن المؤقت.

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

نصائح أخرى

وA segfault يتم الوصول إلى الذاكرة التي كنت لا يسمح الوصول إليها. للقراءة فقط ذلك، لم يكن لديك إذن، الخ ...

وتحاول خطأ حافلة للوصول إلى الذاكرة التي لا يمكن أن تكون هناك. كنت قد استخدمت عنوان هذا لا معنى له على النظام، أو الخطأ نوع من عنوان لتلك العملية.

<اقتباس فقرة>   

وأعتقد أن نواة تثير SIGBUS   عندما يكون هناك تطبيق يعرض البيانات   اختلالها على ناقل البيانات. أعتقد   هذا لأن معظم [؟] المجمعين الحديثة   بالنسبة لمعظم المعالجات لوحة / محاذاة   البيانات للمبرمجين، و   مشاكل المواءمة بين ماض (على الأقل)   التخفيف، وبالتالي واحدة لا ترى   SIGBUS في كثير من الأحيان في هذه الأيام (AFAIK).

ومن: هنا

mmap الحد الأدنى من مثال POSIX 7

يحدث "خطأ الناقل" عندما ترسل النواة SIGBUS إلى عملية.

الحد الأدنى من الأمثلة التي تنتج ذلك لأنه ftruncate تم نسيانه:

#include <fcntl.h> /* O_ constants */
#include <unistd.h> /* ftruncate */
#include <sys/mman.h> /* mmap */

int main() {
    int fd;
    int *map;
    int size = sizeof(int);
    char *name = "/a";

    shm_unlink(name);
    fd = shm_open(name, O_RDWR | O_CREAT, (mode_t)0600);
    /* THIS is the cause of the problem. */
    /*ftruncate(fd, size);*/
    map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    /* This is what generates the SIGBUS. */
    *map = 0;
}

إركض مع:

gcc -std=c99 main.c -lrt
./a.out

تم الاختبار في أوبونتو 14.04.

بوسيكس يصف SIGBUS مثل:

الوصول إلى جزء غير محدد من كائن الذاكرة.

ال مواصفات mmap يقول ان:

يجب أن تؤدي المراجع الموجودة ضمن نطاق العنوان بدءًا من pa واستمرار وحدات بايت len إلى الصفحات الكاملة بعد نهاية الكائن إلى تسليم إشارة SIGBUS.

و shm_open يقول ان يقوم بإنشاء كائنات بالحجم 0:

كائن الذاكرة المشتركة له حجم صفر.

حتى في *map = 0 نحن نلمس الماضي نهاية الكائن المخصص.

الوصول إلى ذاكرة المكدس غير المحاذاة في ARMv8 aarch64

وقد ذكر ذلك في: ما هو خطأ الحافلة؟ بالنسبة لـ SPARC، ولكن هنا سأقدم مثالًا أكثر قابلية للتكرار.

كل ما تحتاجه هو برنامج aarch64 قائم بذاته:

.global _start
_start:
asm_main_after_prologue:
    /* misalign the stack out of 16-bit boundary */
    add sp, sp, #-4
    /* access the stack */
    ldr w0, [sp]

    /* exit syscall in case SIGBUS does not happen */
    mov x0, 0
    mov x8, 93
    svc 0

يقوم هذا البرنامج بعد ذلك برفع SIGBUS على Ubuntu 18.04 aarch64 و Linux kernel 4.15.0 في جهاز خادم ThunderX2.

لسوء الحظ، لا يمكنني إعادة إنتاجه في وضع المستخدم QEMU v4.0.0، لست متأكدًا من السبب.

يبدو أن الخطأ اختياري ويتم التحكم فيه بواسطة SCTLR_ELx.SA و SCTLR_EL1.SA0 الحقول، لقد لخصت المستندات ذات الصلة أبعد قليلا هنا.

ويمكنك أيضا الحصول على SIGBUS عندما صفحة رموز لا يمكن ترحيلها في لسبب ما.

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

unsigned char data[6];
(unsigned int *) (data + 2) = 0xdeadf00d;

يحاول هذا المقتطف كتابة قيمة عددية 32 بت 0xdeadf00d إلى عنوان (على الأرجح) لم تتم محاذاته بشكل صحيح، وسيؤدي إلى حدوث خطأ في الناقل على البنيات "الصعبة الإرضاء" في هذا الصدد.إنتل x86، بالمناسبة، لا مثل هذه البنية، ستسمح بالوصول (وإن كان تنفيذها أبطأ).

وذلك يعتمد على نظام التشغيل الخاص بك، وحدة المعالجة المركزية، مترجم، وعوامل أخرى ربما.

في عام فهذا يعني أن حافلة CPU تعذر إتمام أمر ما، أو تعاني من الصراع، ولكن هذا قد يعني مجموعة كاملة من الأشياء اعتمادا على البيئة ورمز يتم تشغيل.

و-Adam

وهذا يعني عادة وصول الانحياز الامم المتحدة.

ومحاولة الوصول إلى ذاكرة غير موجود جسديا من شأنه أيضا أن يعطي خطأ الحافلة، ولكنك لن ترى هذا إذا كنت تستخدم معالج مع MMU وOS هذا ليس عربات التي تجرها الدواب، لأنك لن تقوم وأي ذاكرة غير موجودة تعيينها إلى مساحة عنوان العملية الخاص بك.

وهناك مثال محدد من الخطأ حافلة أنا فقط واجهت في حين البرمجة C على OS X:

#include <string.h>
#include <stdio.h>

int main(void)
{
    char buffer[120];
    fgets(buffer, sizeof buffer, stdin);
    strcat("foo", buffer);
    return 0;
}

في حال كنت لا تذكر strcat مستندات يلحق الوسيطة الثانية إلى الأولى عن طريق تغيير الوسيطة الأولى (الوجه الحجج وأنه يعمل بشكل جيد). على لينكس هذا يعطي خطأ تجزئة (كما هو متوقع)، ولكن على OS X أنه يعطي خطأ الحافلة. لماذا ا؟ أنا حقا لا أعرف.

وكنت الحصول على خطأ الحافلة عندما كان الدليل الجذر عند 100٪.

وكان لي سبب الخطأ حافلة على نظام التشغيل Mac OS X التي حاولت تخصيص حوالي 1MB على المكدس. هذا وعملت جيدا في موضوع واحد، ولكن عند استخدام قانون الزواج هذا يدفع إلى خطأ حافلة، لأن ماك OS X محدودة جدا <وأ href = "https://groups.google.com/a/chromium.org/forum/#!topic / الكروم ونقد / DMt5bDdK7s8 "يختلط =" نوفولو "> حجم مكدس للمواضيع غير الرئيسية .

للإضافة إلى ما أجاب عليه blxtd أعلاه، تحدث أخطاء الناقل أيضًا أثناء العملية لا يمكن محاولة الوصول إلى ذاكرة "متغير" معين.

for (j = 0; i < n; j++) {
                for (i =0; i < m; i++) {
                        a[n+1][j] += a[i][j];
                }
        }

لاحظ ال 'عن غير قصد' استخدام المتغير "أنا" في ال أولا "للحلقة"؟ هذا هو سبب خطأ الحافلة في هذه الحالة.

ولقد اكتشفت بالطريقة الصعبة أن على معالج مع ARMv7 يمكنك كتابة بعض الرموز التي تمنحك خطأ تجزئة عند غير محسن، ولكن يعطيك خطأ حافلة عند التحويل البرمجي مع -O2 (تحسين أكثر). أنا أستخدم دول مجلس التعاون الخليجي مترجم ذراع gnueabihf عرضية من إلى x64 أوبونتو.

وأنا أتفق مع جميع الإجابات المذكورة أعلاه.فيما يلي سنتي فيما يتعلق بخطأ BUS:

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

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

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

وهناك تجاوز سعة المخزن المؤقت نموذجية مما يؤدي إلى خطأ الناقل هو،

{
    char buf[255];
    sprintf(buf,"%s:%s\n", ifname, message);
}

وهنا إذا كان حجم السلسلة في التنصيص ( "") هو أكثر من حجم BUF أنه يعطي خطأ الحافلة.

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