دفع استدعاء المحكمة الخاصة بلبنان الانتظار<std::string> أسباب Segfault عندما سلسلة قراءة من مأخذ

StackOverflow https://stackoverflow.com/questions/1618244

سؤال

أنا باستخدام STL طابور كمدخل طابور انها تحتوي على std::السلاسل التي لدي مستعارة مثل سلسلة باستخدام الرموز المميزة ل typedef.أنا أقرأ إدخال سلسلة من المقبس - باستخدام بيركلي مآخذ.بل هو قراءة في شار مجموعة عازلة ومن ثم استخدام مجموعة سلسلة التي يتم تمريرها إلى الانتظار.يحدث ذلك فقط من أجل إدخال قائمة الانتظار في قائمة انتظار الإخراج التي لا تلقي لها سلاسل من المقبس قراءة يعمل بشكل جيد.

هنا هو رمز ذات الصلة:

// Read from this socket's descriptor and send the input
// to its associated player for queueing and parsing.
void Socket::Read() {
 char buf[READ_SIZE + 1];

 int n = 0;
 if ((n = read(descriptor, buf, READ_SIZE)) < 0) {
  try {
   handleSocketError(__FILE__, __LINE__);
  }
  catch (...) {
   throw ;
  }
 }
 else if(n > 0) {
  buf[n] = 0;
  stripNewline(buf);
  log->log("Input received in Socket::Read: %s.", buf);
  String in = buf;
  p->input(in);
 }
}

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

// A utility function to strip the newlines off the end of
// a string.
void Socket::stripNewline(char *buf) {
 for(int i = strlen(buf); i > 0 && (buf[i] == '\n' || buf[i] == '\r' || buf[i] == 0); i--) {
   buf[i] = 0;
 }
}

هذا هو حيث المدخلات ينشأ و يتم تغذية p->الإدخال كسلسلة.p->الإدخال يدفع ببساطة سلسلة الإدخال على قائمة الانتظار:

// Push the String in to the tail of the input queue.
void Player::input(String in) {
 log->log("Player is sending input: %s.", in.c_str());
 std::cout << in << std::endl;
 inQ.push(in);
}

في انتظار يعرف هنا في الداخل لاعب الطبقة جنبا إلى جنب مع قائمة الانتظار التي تعمل بشكل جيد:

std::queue<String> inQ;
std::queue<String> outQ;

سلسلة تعريفها ببساطة بأنها typedef من std::string:

typedef std::string String;

تحرير:ثابت إلى الوراء typedef ما أحصل عليه من كتابته من الذاكرة عندما يصرف كان الصحيح في التعليمات البرمجية.

الإخراج قبل تجزئة الخطأ الناتج من catchsegv هو ما يلي:

Sat Oct 24 11:02:34 2009:: New connection, waking up.
Sat Oct 24 11:02:34 2009:: Connection attempt begun.  Connection in the read set.
Sat Oct 24 11:02:34 2009:: Player has received output: Welcome to Muddy Reality Alpha version!
.
Sat Oct 24 11:02:35 2009:: Input received in Socket::Read: test.
Sat Oct 24 11:02:35 2009:: Player is sending input: test.
test
Segmentation fault
*** Segmentation fault
Register dump:

 EAX: 0000000c   EBX: 00000080   ECX: 00000000   EDX: 0000000c
 ESI: bfdbf080   EDI: 080497e0   EBP: bfdbee38   ESP: bfdbee20

 EIP: 0805640f   EFLAGS: 00010282

 CS: 0073   DS: 007b   ES: 007b   FS: 0000   GS: 0033   SS: 007b

 Trap: 0000000e   Error: 00000004   OldMask: 00000000
 ESP/signal: bfdbee20   CR2: 00000024

 FPUCW: ffff037f   FPUSW: ffff0000   TAG: ffffffff
 IPOFF: 00000000   CSSEL: 0000   DATAOFF: 00000000   DATASEL: 0000

 ST(0) 0000 0000000000000000   ST(1) 0000 0000000000000000
 ST(2) 0000 0000000000000000   ST(3) 0000 0000000000000000
 ST(4) 0000 0000000000000000   ST(5) 0000 0000000000000000
 ST(6) 0000 0000000000000000   ST(7) 0000 0000000000000000

Backtrace:
/lib/libSegFault.so[0xb7f9e100]
??:0(??)[0xb7fa3400]
/usr/include/c++/4.3/bits/stl_queue.h:226(_ZNSt5queueISsSt5dequeISsSaISsEEE4pushERKSs)[0x805647a]
/home/dbingham/src/middle-earth-mud/alpha6/src/engine/player.cpp:73(_ZN6Player5inputESs)[0x805377c]
/home/dbingham/src/middle-earth-mud/alpha6/src/engine/socket.cpp:159(_ZN6Socket4ReadEv)[0x8050698]
/home/dbingham/src/middle-earth-mud/alpha6/src/engine/socket.cpp:413(_ZN12ServerSocket4ReadEv)[0x80507ad]
/home/dbingham/src/middle-earth-mud/alpha6/src/engine/socket.cpp:300(_ZN12ServerSocket4pollEv)[0x8050b44]
/home/dbingham/src/middle-earth-mud/alpha6/src/engine/main.cpp:34(main)[0x8049a72]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0xb7d1b775]
/build/buildd/glibc-2.9/csu/../sysdeps/i386/elf/start.S:122(_start)[0x8049801]

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

تحريره لإضافة نتائج استمرار بدس:

لقد حاول اثنين من الأساليب الأخرى من وضع buf في السلسلة أن يذهب إلى p->الإدخال:

p->input(String(buf));

و

String in;
in.assign(buf);
p->input(in);

سواء كان نفس النتيجة.لقد حاولت إرسال المخزن المؤقت إلى معيار خارج حرف للتأكد من عدم وجود أحرف غريبة تسللت في:

 printf("Printing buf to determine sanity: \n");
 for(int i = 0; buf[i] != 0; i++) {
  printf("%d: %c\n", i, buf[i]);
 }

وكانت النتيجة:

Printing buf to determine sanity: 
0: T
1: e
2: s
3: t

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

أبعد من ذلك:كان في الأصل size_t (صحيح غير الموقعة نوع) يجري مقارنة للقيم أقل من الصفر.تغير كل ssize_t (صحيح وقعت نوع) و مستقيم الباحث مع أي تغيير - لا تزال تعطل.شكرا كريس ليس هو الحل ولكن لا تزال جيدة الصيد!

أجاب:أنا بحماقة في عش برنامج, نسيت أن تعيين لاعب *p في المقبس الدرجة.ف هو العودة الرابط بين مقبس لاعب التي تحتوي عليه.كنت من المفترض أن p بخير لأننا كنا يجعل ذلك في عمق لاعب قبل تحطمها ، وبالتالي كان لا بد من شيء مع سلسلة أو الانتظار.سخيف لي.شكرا كريس!

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

المحلول

size_t هو غير موقعة نوع ، n هو size_t لذلك هذه المقارنة لن يكون صحيحا.

if ((n = read(descriptor, buf, READ_SIZE)) < 0) {

إذا read يعود -1, ثم هذا else if سوف محاولة التلاعب العازلة حقا كبيرة العازلة:

else if(n > 0) {

أنا لست متأكدا مما إذا كان من القضايا التي لقد أبرزت تسبب مشكلة لكنها تستحق التثبيت.

تحرير

حسنا, اتضح أن هذا لم يكن في المسألة ، ولكن أعتقد من وجهة الحادث كان من الممكن أن يكون (كان!) أن Player مؤشر p كانت فارغة.

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