[C] Segmentation fault in curses lib.

Pagina: 1
Acties:

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-07 21:46

Confusion

Fallen from grace

Topicstarter
Ik wilde in een programma graag reageren op een keypress en dacht dat met
curses te kunnen bereiken. Helaas, het onderstaande programma eindigt met een
segmentation fault. De printf("Press 'q' [..]") wordt niet meer
uitgevoerd, hoewel gdb aangeeft dat de segmentation fault pas in de
wgetch() functie in curses.c optreedt. Ik heb geen flauw idee wat er aan
de hand zou kunnen zijn; heeft iemand hier een idee?
[Dit is de minimale versie van het programma waarin ik het probleem kan
demonstreren; dit programma zelf doet niets zinnigs]

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <string.h>
#include <curses.h>

int main(void) {
  char kw[30];
  char desc[200];
  int answ;
  do {
    strcpy(kw, "Keyword");
    strcpy(desc, "Description");

    printf("%s:\n\t%s\n", kw, desc);
    printf("Press 'q' to quit browsing; any other key to display the next entry.");

    answ = getch();
  } while (answ != 'q');
  return 0;
}

edit:
Ik compileer het programma met: gcc -Wall -ansi -pedantic -o progname progname.c -lm -lncurses
Dit levert geen fouten of waarschuwingen

[ Voor 11% gewijzigd door Confusion op 23-07-2003 19:01 ]

Wie trösten wir uns, die Mörder aller Mörder?


  • _Squatt_
  • Registratie: Oktober 2000
  • Niet online
De printf("Press 'q' to..."); wordt wel uitgevoerd, maar omdat er geen '\n' op het eind staat wordt de tekst gebufferd, en dus niet meteen naar het scherm geschreven.

De segfault komt omdat voordat je (n)curses functies kunt gebruiken je eerst initscr(); moet aanroepen. Dit (en meer) staat bij mij in de manpage ncurses(3x). Na even spelen ben ik er niet zo snel achter hoe je ncurses en printf() kunt afwisselen, dus misschien moet je je tekst ook met behulp van ncurses op het scherm zetten.

"He took a duck in the face at two hundred and fifty knots."


  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-07 21:46

Confusion

Fallen from grace

Topicstarter
_Squatt_ schreef:
De printf("Press 'q' to..."); wordt wel uitgevoerd, maar omdat er geen '\n' op het eind staat wordt de tekst gebufferd, en dus niet meteen naar het scherm geschreven.
Ehmm ja, ik realiseer me nu ook dat ik daar eerst een fflush had staan :)
De segfault komt omdat voordat je (n)curses functies kunt gebruiken je eerst initscr(); moet aanroepen. Dit (en meer) staat bij mij in de manpage ncurses(3x).
Dan kan ik niet goed lezen, want die pagina heb ik al een paar keer voor m'n snufferd gehad.

Wie trösten wir uns, die Mörder aller Mörder?


  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-07 21:46

Confusion

Fallen from grace

Topicstarter
Laat ik de vraag anders stellen: is het mogelijk in C keyboard input af te vangen zonder dat er eerst op return gedrukt hoeft te worden? Met curses kan het wel, maar dan verandert meteen de hele manier van input/output en dat is net minder handig, aangezien ik dan een groot deel moet gaan herschrijven, wat de moeite uiteindelijk niet waard is.

Wie trösten wir uns, die Mörder aller Mörder?


  • deadinspace
  • Registratie: Juni 2001
  • Laatst online: 21-08 13:51

deadinspace

The what goes where now?

Fused schreef op 23 juli 2003 @ 22:22:
Laat ik de vraag anders stellen: is het mogelijk in C keyboard input af te vangen zonder dat er eerst op return gedrukt hoeft te worden? Met curses kan het wel, maar dan verandert meteen de hele manier van input/output en dat is net minder handig, aangezien ik dan een groot deel moet gaan herschrijven, wat de moeite uiteindelijk niet waard is.
Dat heeft op zich niks met C te maken; het zijn de Unix terminals (GNU/Linux' TTYs en terminal emulators bv) die dat doen. Standaard is de input/output line-buffered, om de performance te verbeteren. In line-buffered mode kan de terminal namelijk wachten tot er meer data binnen is (typisch een hele regel) en die in één keer displayen. Voor geintjes zoals jij wil is character-buffered I/O nodig.

Je kunt je terminal character buffered I/O laten doen door een ioctl() op het terminal device dacht ik, maar dit is waarschijnlijk redelijk systeem-specifiek (dwz, dat het in GNU/Linux werkt wil niet zeggen dat het in andere OSsen ook werkt). Dit is in principe ook wat ncurses doet, maar ncurses verbergt de systeem-specifieke dingen voor je.

  • igmar
  • Registratie: April 2000
  • Laatst online: 29-06 18:56

igmar

ISO20022

Fused schreef op 23 July 2003 @ 18:56:
Ik wilde in een programma graag reageren op een keypress en dacht dat met
curses te kunnen bereiken. Helaas, het onderstaande programma eindigt met een
segmentation fault. De printf("Press 'q' [..]") wordt niet meer
uitgevoerd, hoewel gdb aangeeft dat de segmentation fault pas in de
wgetch() functie in curses.c optreedt
Da's logisch, stdout is line-buffered.
. Ik heb geen flauw idee wat er aan
de hand zou kunnen zijn; heeft iemand hier een idee?
Uit man 3 ncurses :

code:
1
2
3
To initialize the routines, the routine initscr or newterm
must  be called before any of the other routines that deal
with windows and screens are  used.


Curses is trouwens hier nogal een bloated oplossing, zeker als je alleen maar je terminal unbuffered wil hebben.

code:
1
2
3
4
5
struct termios current;

tcgetattr(0, &current);
normal.lflag &= ~ICANON;
tcsetattr(0, TCSADRAIN, &current);


Zou hetzelfde moeten doen. Zie de manpage van tcsetattr voor de beschrijven van de waslijst met flags die je kan instellen. Bovenstaande is even uit het hoofd, dus totaal ongetest :)

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-07 21:46

Confusion

Fallen from grace

Topicstarter
deadinspace schreef:
Je kunt je terminal character buffered I/O laten doen door een ioctl() op het terminal device dacht ik, maar dit is waarschijnlijk redelijk systeem-specifiek (dwz, dat het in GNU/Linux werkt wil niet zeggen dat het in andere OSsen ook werkt).
Heb een beetje door dingen als vt.h, vt_buffer.h, manpages van tty, console, etc. heen zitten bladeren, maar echt makkelijk is het niet.
Voor de search: http://www.mit.edu/afs/si...er/daveg/Src/unbuffered.c (niet getest overigens).
igmar schreef:
Curses is trouwens hier nogal een bloated oplossing, zeker als je alleen maar je terminal unbuffered wil hebben.
My thoughts exactly :)
[..]
Zou hetzelfde moeten doen. Zie de manpage van tcsetattr voor de beschrijven van de waslijst met flags die je kan instellen. Bovenstaande is even uit het hoofd, dus totaal ongetest :)
OK, bedankt. Ik geloof dat het een beetje teveel moeite voor dit lullige programmaatje begint te worden om dit te implementeren. Dan maar een extra vereisen :)

Even iets anders: op welke manier zijn jullie hier achter gekomen?

Wie trösten wir uns, die Mörder aller Mörder?


  • deadinspace
  • Registratie: Juni 2001
  • Laatst online: 21-08 13:51

deadinspace

The what goes where now?

Fused schreef op 24 juli 2003 @ 12:16:
Heb een beetje door dingen als vt.h, vt_buffer.h, manpages van tty, console, etc. heen zitten bladeren, maar echt makkelijk is het niet.
Je zou igmars oplossing met tcsetattr() eens kunnen proberen... Als die werkt, dan is het niet zoveel werk, en het is volgensmij vrij portable.
Even iets anders: op welke manier zijn jullie hier achter gekomen?
Veel lezen (zoals de ncurses docs en manpages) :)

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-07 21:46

Confusion

Fallen from grace

Topicstarter
deadinspace schreef:
Veel lezen (zoals de ncurses docs en manpages) :)
Mjah, maar daar kan ik niet altijd wijs uit worden. Goed, in dit geval had ik het gewoon onderschat, wat niet zo goed is voor je manier van zoeken, maar ik heb wel eerder meegemaakt dat ik werkelijk alles gelezen had dat los en vast zat en ik er vervolgens nog steeds niet uitkwam, waarop iemandanders vervolgens binnen 5 minuten de oplossing had. Toen heb ik alleen niet gevraagd waar hij z'n info vandaan had, maar dat doe ik tegenwoordig maar wel. Ik kan me een geval herinneren waarbij iemand de oplossing wist omdat een paar jaar ervaring in Delphi had en "er inderdaad geen documentatie over beschikbaar is".

Wie trösten wir uns, die Mörder aller Mörder?


  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-07 21:46

Confusion

Fallen from grace

Topicstarter
Het inverse van
normal.lflag &= ~ICANON is toch
normal.lflag |= ICANON?

(even een sanity check :))

edit:
Nevermind: het werkt :) Bedankt!

[ Voor 20% gewijzigd door Confusion op 25-07-2003 13:28 ]

Wie trösten wir uns, die Mörder aller Mörder?


  • igmar
  • Registratie: April 2000
  • Laatst online: 29-06 18:56

igmar

ISO20022

Fused schreef op 25 July 2003 @ 13:25:
Het inverse van
normal.lflag &= ~ICANON is toch
normal.lflag |= ICANON?
Yep.
Pagina: 1