Domanda

Sto usando una coda STL come coda di input, che contiene std :: stringhe, che ho impostato come stringa usando un typedef. Sto leggendo la stringa di input da un socket - usando i socket Berkeley. Viene letto in un array di buffer di caratteri e quindi utilizzato per impostare una stringa che viene passata alla coda. Succede solo per la coda di input - la coda di output, che non riceve le sue stringhe dal socket letto, funziona bene.

Ecco il codice pertinente:

// 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);
 }
}

La funzione stripNewline è una funzione di utilità per eliminare le righe dalla fine l'input ricevuto. L'ho inserito per facilitare il debug, non era presente quando è apparso il 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;
 }
}

Qui è dove ha origine l'input ed è inserito in p- > input come una stringa. p- > input inserisce semplicemente la stringa di input nella coda:

// 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);
}

La coda di ingresso è definita qui all'interno della classe del giocatore insieme alla coda di uscita, che funziona bene:

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

La stringa è definita semplicemente come un typedef di std :: string:

typedef std::string String;

EDIT : risolto errore di battitura all'indietro, quello che ottengo per scriverlo dalla memoria quando distratto, era corretto nel codice.

L'output prima dell'errore di segmentazione e l'output di catchsegv è il seguente:

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]

Quasi come posso dire che String è sano, quindi non ho idea di cosa potrebbe far soffocare la coda. Continuerò a frugarlo e vedrò cosa mi presenterò, ma apprezzerei davvero tutte le intuizioni che la community di Stack Overflow può offrire su questo.

MODIFICATO per aggiungere i risultati della ricerca continua:

Ho provato altri due metodi per inserire buf nella stringa che va in input p- >

p->input(String(buf));

e

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

Entrambi hanno avuto lo stesso risultato. Ho provato a inviare il buffer allo standard carattere per carattere per assicurarmi che nessun personaggio strano si intrufolasse:

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

Il risultato è stato:

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

Quindi ancora nessuna idea. È tutta memoria statica locale, quindi non è un problema di memoria dymanic a meno che non sia davvero strano (ovviamente, memoria dinamica === strani problemi, quindi è ancora una possibilità).

Inoltre: originariamente aveva size_t (un tipo intero senza segno) che veniva confrontato per valori inferiori a zero. Modificato sia in un ssize_t (tipo intero con segno) che in un semplice int senza modifiche - continua a bloccarsi. Grazie Chris, non la risposta ma comunque una buona cattura!

Risposto : scioccamente, nel mio nido di un programma, ho dimenticato di impostare Player * p nella classe Socket. P è il collegamento posteriore tra il Socket e il Player che lo contiene. Avevo supposto che p andasse bene perché lo stavamo trasformando così profondamente nel giocatore prima di andare in crash, e quindi doveva essere qualcosa con la stringa o la coda. Sciocco me Grazie Chris!

È stato utile?

Soluzione

size_t è un tipo senza segno, n è un size_t quindi questo confronto non sarà mai vero.

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

Se read restituisce -1 , questo altrimenti if proverà a manipolare il buffer come un buffer veramente grande:

else if(n > 0) {

Non sono sicuro se i problemi che ho evidenziato stiano causando un problema, ma vale la pena risolverli.

Modifica

OK, si scopre che quello non era il problema, ma indovinando dal punto dello schianto avrebbe potuto essere (ed era!) che il puntatore Player p era null.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top