[C] non-malloc geheugenfouten opsporen

Pagina: 1
Acties:

  • raoulduke
  • Registratie: Oktober 2003
  • Niet online
Het uiteindelijke probleem dat ik heb is dat een (lang)lopende C-applicatie een segmentation fault veroorzaakt en core dumpt, waardoor ik het vermoeden heb dat er ergens met de geheugentoewijzing en het uitlezen niet goed gaat, bijvoorbeeld arrays die buiten de boundaries worden gelezen.

De applicatie draait op een Sun SPARC met Solaris 2.8.

Ik heb verschillende memory debuggers gevonden die geheugen dat ge-malloc-ed en niet ge-free-d wordt kunnen opsporen, bijvoorbeeld Electric Fence, MPatrol en CheckerGCC. Geen van deze tools vindt fouten in de volgende code:
code:
1
2
3
4
5
int main(int argc, char** argv) {
    int test[2];
    test[4] = 9;
    return 0;
}

Ik heb me al afgevraagd waarom dit niet tot problemen leidt, misschien komt dit omdat geheugenpagina's in blokken worden toegekend in plaats van per byte? Als ik namelijk als index 4000 gebruik in plaats van '4' dan komt er wel een segmentation fault die getrapt wordt door MPatrol.

Is het mogelijk om dit soort kleine afwijkingen in de addressering van arrays en andere variabelen te achterhalen met een bepaalde tool? Valgrind kan ik volgens mij niet gebruiken omdat dat alleen op een x86-achtig platform werkt.

Elke hint of tip is welkom.

Remember, if you have any trouble you can always send a telegram to the Right People.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 28-04 14:41

.oisyn

Moderator Devschuur®

Demotivational Speaker

Tja, purify en boundschecker, maar beide ook x86 only als ik me niet vergis helaas.

En waarom het niet tot problemen leidt is puur toeval, ik gok dat je op een x86 de oude waarde van ebp overschrijft, waardoor de aanroepende functie niet meer bij z'n lokale variabelen kan en de stack verneukt wordt. Maar aangezien in de aanroepende functie waarschijnlijk iets staat als: exit(main(argc, argv)), wordt exit meteen aangeroepen en gaat alles prima.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Rukapul
  • Registratie: Februari 2000
  • Laatst online: 23:33
Wordt test[2] soms op de stack gealloceerd en is het daarom niet direct fataal?

Kun je je applicatie niet ook op x86 onder Linux kunnen compileren? Valgrind markeert zeer goed de locaties die gealloceerd zijn en of er niet gealloceerd geheugen aangesproken wordt. Weet overigens niet in hoeverre dit ook geldt voor de stack.

  • alx
  • Registratie: Maart 2002
  • Niet online

alx

Idd lijkt het me het makkelijkst als je het op een x86 machine kan draaien, want dan kun je
o.a. valgrind gebruiken.
Als er geen variant voor solaris/sparc is, heb je een source code checker nodig.
Enige tijd geleden heb ik naar zo'n tool gezocht en niet echt naar tevredenheid gevonden.
Ik denk dat Coverity (http://www.coverity.com/) erg handig is, maar ik denk dat dat een hoop kost.
Wat overblijft is Splint (http://lclint.cs.virginia.edu/), een uitbereiding van lint, gemaakt aan de
uni van virginia. Zelf nooit geprobeerd. Het werkt pas optimaal als je je source annotate, maar ook
zonder kan het C code analyseren.
Als je het probeert, post dan het resultaat; ik ben eigenlijk ook wel benieuwd.

  • raoulduke
  • Registratie: Oktober 2003
  • Niet online
Bedankt voor de suggesties tot nu toe, ik heb een UNIX trial versie van Purify via IBM aangevraagd, maar ik wacht nog op bevestiging ivm exportrestricties vanuit Amerika. Valgrind is een ultiem handige tool voor dit probleem, maar ik kan het programma niet naar Linux / x86 omzetten in verband met hardwaredrivers die alleen voor Solaris SPARC te krijgen zijn.

Statische code controle zoals lint kan ik nog proberen, ik zal kijken of dat iets oplevert. Vooralsnog ga ik eerst proberen of ik met MPatrol iets nuttigs kan achterhalen als de segfault voorkomt.

Het verschil tussen stack- en heapcorruptie kan zoals enkelen zeiden inderdaad ook een obstakel vormen voor de genoemde tools, maar daar kan ik eigenlijk weinig aan veranderen. Goh, wat zou ik nu graag een Valgrind hebben voor SPARC...

Remember, if you have any trouble you can always send a telegram to the Right People.


  • igmar
  • Registratie: April 2000
  • Laatst online: 20-04 22:06

igmar

ISO20022

raoulduke schreef op vrijdag 23 september 2005 @ 14:11:
Goh, wat zou ik nu graag een Valgrind hebben voor SPARC...
Valgrind detecteerd geen overflows in stratische of stack arrays. D'r is een gcc patch die ervoor zorgt dat je applicatie abort() indien dat gebeurd, maar dat betekend dus je gcc patchen.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23:38
Onder Windows heb je de mogelijkheid om een exception handler te installleren bij dit soort dingen. Misschien kun je wat doen door een signal handler te installeren ofzo. Nadeel is dat de moet gaan zitten coden, maar het heeft mij al wel eens uit de brand geholpen.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • raoulduke
  • Registratie: Oktober 2003
  • Niet online
Ik ben nog geen stap verder: MPatrol is onbruikbaar omdat het "kleine" fouten in de array-indexering niet kan vinden omdat er geen segfaults optreden, het vindt alleen malloc-problemen die in libc time functies voorkomen, maar dan is het kwaad al geschied, de time functies zelf zijn namelijk gewoon goed.

Mijn Rational Purify demo heb ik nog niet binnen van IBM en ik heb ook weinig hoop dat dat nog gaat gebeuren. Ik heb splint getest, maar door een wirwar aan hardware library headerfiles die geinclude worden waarin dan ook nog eens fouten zitten is het tooltje al snel de weg kwijt, jammer maar helaas.

De beste oplossing die ik nu nog zie is om met assert() alle variabelen en indices te gaan controleren. OK, gaat er dan wat mis dan stopt het programma, maar dan weet ik wel in welke file en welke regel het misgaat. Zowieso moeten alle problemen eruit dus ik zie geen hindernissen in het toevoegen van assert()s.

Ik laat het weten als ik Purify kan testen, of als ik met assert() eruit ben, ik hoop er deze week uit te kunnen komen.

Remember, if you have any trouble you can always send a telegram to the Right People.


  • windancer
  • Registratie: Maart 2000
  • Laatst online: 28-04 22:01
Wat ik op Solaris ook wel gebruik naast Purtify is Insure. Meer info op http://www.parasoft.com/j...?product=Insure&itemId=63

  • windancer
  • Registratie: Maart 2000
  • Laatst online: 28-04 22:01
Oh, en als hij core dumpt kun je de core bekijken met een debugger. Misschien kun je daar iets uit halen. Je kunt dan ten minste alle variabelen bekijken en een stack trace van de fout bekijken.

  • igmar
  • Registratie: April 2000
  • Laatst online: 20-04 22:06

igmar

ISO20022

raoulduke schreef op zondag 25 september 2005 @ 21:22:
Ik ben nog geen stap verder: MPatrol is onbruikbaar omdat het "kleine" fouten in de array-indexering niet kan vinden omdat er geen segfaults optreden, het vindt alleen malloc-problemen die in libc time functies voorkomen, maar dan is het kwaad al geschied, de time functies zelf zijn namelijk gewoon goed.
Ik vrees toch dat je het met gcc boundschecking zal moeten doen. Het vereist wel een gcc recompile, maar dat beschouw ik zelf niet echt als een probleem. Ik heb de patch ook een aantal keren gebruik, en hij doet eigenlijk precies wat jij wil :

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
igmar@ouzo:~$ ./x
Bounds Checking GCC v gcc-4.0.1-3.2 Copyright (C) 1995 Richard W.M. Jones
Bounds Checking comes with ABSOLUTELY NO WARRANTY. For details see file
`COPYING' that should have come with the source to this program.
Bounds Checking is free software, and you are welcome to redistribute it
under certain conditions. See the file `COPYING' for details.
For more information, set GCC_BOUNDS_OPTS to `-help'
x.c:10:Bounds error: array reference (11) outside bounds of the array.
x.c:10:  Pointer value: 0xbf94dbe0
x.c:10:  Object `a':
x.c:10:    Address in memory:    0xbf94dbb4 .. 0xbf94dbdb
x.c:10:    Size:                 40 bytes
x.c:10:    Element size:         4 bytes
x.c:10:    Number of elements:   10
x.c:10:    Created at:           x.c, line 8
x.c:10:    Storage class:        stack
Aborted


met deze code :

code:
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int main(int argc, char **argv)
{
        int a[10];

        a[11] = 5;

        return 0;
}

[ Voor 42% gewijzigd door igmar op 26-09-2005 15:24 ]


  • raoulduke
  • Registratie: Oktober 2003
  • Niet online
Bedankt voor de tussentijdse tips allemaal!

Ik heb van de week het programma op de pijnbank gelegd en een manier gevonden om het in zeer korte tijd te laten core-en. Ik heb de backtraces geanalyseerd met mdb waaruit bleek dat de core dump voornamelijk plaatsvond op de functie localtime().

In de Solaris man-pages gaan zoeken en daaruit bleek dat deze functie niet threadsafe is. Het programma draait echter op 60 threads die allemaal localtime() regelmatig aanroepen. Ik heb alle voorkomens van de functie localtime() nu vervangen door localtime_r() die wel threadsafe is.

Tot nu toe geen core dumps, maar ik heb nog geen 100% zekerheid. Ik ga de genoemde alternatieven, Insure en de boundschecking patch voor gcc eens onder de loep nemen, zodat ik kan uitsluiten dat er buiten arrays wordt gelezen of geschreven. Mijn eerste test met het assert()-en van alle array- en structstatements leverde geen gekke dingen op.

Remember, if you have any trouble you can always send a telegram to the Right People.


  • igmar
  • Registratie: April 2000
  • Laatst online: 20-04 22:06

igmar

ISO20022

raoulduke schreef op donderdag 29 september 2005 @ 19:25:
Ik heb van de week het programma op de pijnbank gelegd en een manier gevonden om het in zeer korte tijd te laten core-en. Ik heb de backtraces geanalyseerd met mdb waaruit bleek dat de core dump voornamelijk plaatsvond op de functie localtime().
Dat is eigenlijk al uit het prototype af te leiden : Je stop er niks in, en toch krijg je wat terug. Misschien eens tijd voor een lijst met non-threadsafe en non-async-safe functies, zodat je weet wat je niet in threaded apps en signal handlers moet gebruiken.
Tot nu toe geen core dumps, maar ik heb nog geen 100% zekerheid. Ik ga de genoemde alternatieven, Insure en de boundschecking patch voor gcc eens onder de loep nemen, zodat ik kan uitsluiten dat er buiten arrays wordt gelezen of geschreven. Mijn eerste test met het assert()-en van alle array- en structstatements leverde geen gekke dingen op.
boundschecking is zowiezo altijd nuttig : Kwaad kan het niet om het te gebruiken. Wel even uitzetten in release code :)

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
raoulduke schreef op donderdag 29 september 2005 @ 19:25:
Ik heb van de week het programma op de pijnbank gelegd en een manier gevonden om het in zeer korte tijd te laten core-en. Ik heb de backtraces geanalyseerd met mdb waaruit bleek dat de core dump voornamelijk plaatsvond op de functie localtime().

In de Solaris man-pages gaan zoeken en daaruit bleek dat deze functie niet threadsafe is. Het programma draait echter op 60 threads die allemaal localtime() regelmatig aanroepen. Ik heb alle voorkomens van de functie localtime() nu vervangen door localtime_r() die wel threadsafe is.

Tot nu toe geen core dumps, maar ik heb nog geen 100% zekerheid.
Nee, en sterker nog: ga er maar vanuit dat er meer fouten inzitten. Als je threads in je programma hebt, en localtime() calls, dan heb je dus een programmeur gehad die niet zoveel weet van thread-safe programeren. Die zal meer thread-gerelateerde fouten hebben gemaakt.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • raoulduke
  • Registratie: Oktober 2003
  • Niet online
Even een min of meer korte statusupdate: het serverprogramma werkt nu al een lange tijd onder zware load zonder problemen, sinds ik de calls naar localtime() vervangen heb door localtime_r(). Naast deze wijziging heb ik voor _alle_ array en struct statements assert()'s toegevoegd zodat elke vreemde waarde getrapt wordt.

Voorlopig werkt de applicatie dus probleemloos en ik ben er zeker van dat enige problemen al naar voren gekomen zouden zijn tijdens de testen van de afgelopen weken.Voorlopig zal ik dan ook niet veel tools meer los laten op de code, totdat er natuurlijk alsnog een probleem optreedt; mijn vertrouwen in de applicatie is door het testen en de assert()'s in ieder geval erg gestegen.

Alvast mijn oprechte dank aan iedereen die heeft meegedacht tot nu toe, en ik hoop dat dit topic langzaam naar beneden dwarrelt :)

Remember, if you have any trouble you can always send a telegram to the Right People.


  • windancer
  • Registratie: Maart 2000
  • Laatst online: 28-04 22:01
Dit is eentje voor in het lijstje met "Famous last words" ;)
raoulduke schreef op vrijdag 07 oktober 2005 @ 18:02:
Voorlopig werkt de applicatie dus probleemloos en ik ben er zeker van dat enige problemen al naar voren gekomen zouden zijn tijdens de testen van de afgelopen weken.
Pagina: 1