دفع استدعاء المحكمة الخاصة بلبنان الانتظار<std::string> أسباب Segfault عندما سلسلة قراءة من مأخذ
-
06-07-2019 - |
سؤال
أنا باستخدام 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
كانت فارغة.