Nieuws:

Welkom, Gast. Alsjeblieft inloggen of registreren.
Heb je de activerings-mail niet ontvangen?

Auteur Topic: segmentation fault in c programma  (gelezen 1528 keer)

Offline xellos

  • Lid
segmentation fault in c programma
« Gepost op: 2010/01/18, 22:43:31 »
weet iemand waarom ik een segmentation fault krijg als ik dit draai?

#include <stdio.h>

int multi(getal_a, getal_b)
{
    int som;

    som = getal_a * getal_b;

    return som;
}

#define filename "som.txt"
#define buffersize 1024


int main()
{

  FILE *invoerbestand;

    const int max = 10;
    int getal1 = 10, getal2 = 0;
    int i, som;

    invoerbestand = fopen(filename,"a");
    if(invoerbestand != NULL)
        {
          for(i = 0; i <= max; i++)
          {
          som = multi(getal1, getal2);

          fprintf(invoerbestand, som);
          getal2++;
          }
          fclose(invoerbestand);
        }
        else
        printf("Het bestand %s kon niet worden gecreerd\n", invoerbestand);


 return 0;
}


krijg geen build errors etc.

Offline idefix

  • Lid
Re: segmentation fault in c programma
« Reactie #1 Gepost op: 2010/01/19, 08:46:36 »
Je functie multi moet de types van de argumenten aanduiden:


int multi(int getal_a, int getal_b)
{
    int som;

    som = getal_a * getal_b;

    return som;
}

Verder begrijp ik niet waarom je een variabele "som" declareert waarin je het product van twee getallen stopt? De naam van een variabele moet zoveel mogelijk weerspiegelen waar hij voor staat.
Support bacteria. They're the only culture some people have.

Offline Joshua822

  • Lid
Re: segmentation fault in c programma
« Reactie #2 Gepost op: 2010/01/19, 17:35:20 »
Ik heb toch wat opmerkingen voor je:

Gebruik het preprocessor directive "#define" in plaats van een "const int" variabel*, en gebruik "unsigned short" of "unsigned char" variabelen in plaats van "integer" variabelen als je toch kleine en positieve getallen gaat opslaan in het RAM geheugen !

De variabel "som" in de functie "multi(getal_a,getal_b)" is totaal niet nodig. Je kunt ook gewoon een "return" statement met een wiskundige bewerking schrijven. De wiskundige bewerking zal worden uitgevoerd en de oplossing zal als "return"-waarde fungeren.

De "#define" "buffersize" wordt nergens gebruikt. Dit is een slechte gewoonte. Overigens is het netter om alleen aan de bovenkant van het broncodebestand preprocessor directives te gebruiken.

Ook is het netter om te schrijven "int main(void)", omdat je dan laat weten aan de C compiler dat je gewoon geen argumenten moet geven aan de functie "main()", anders ziet de C compiler het aantal argumenten van de "main()" functie als ongedefinieerd. En dat is natuurlijk niet netjes.   

Je call naar de functie "fprintf" is verkeerd, je vergeet namelijk de "format specifier", deze mag je alleen weglaten als je met de functie een string wegschrijft.

Je zet je call naar de "fclose"" functie op de verkeerde plek. Je zet hem namelijk in de "for" lus, maar aan het begin van de "for" lus open je hem ook niet altijd met de functie "fopen", waardoor je zeker segmentatiefouten zult krijgen, want de bestandspointer variabel "invoerbestand" zal altijd de waarde "NULL" bevatten. Sowieso is het een slecht idee om dit in de "for" lus te doen, want het is een serieuze verspilling van tijd.

*: preprocessor directives nemen geen RAM geheugen in beslag tijdens het uitvoeren, zijn sneller dan constante variabelen omdat de preprocessor, die de C compiler uitvoert voor het compileren van het programma, alle aanroepen naar de constante, gedefinieerd met een "#define" preprocessor directive, vervangt door de waarde, waardoor het programma, eenmaal als het uitgevoerd wordt, niet meer van een andere plek in het geheugen de waarde van de constante variabel zal moeten ophalen. Ook daarom, omdat er niks in het RAM geheugen wordt opgeslagen, zal de constante van je programma niet te veranderen zijn, doordat met een ander programma expres het geheugenadres dat de constante variabel bevat, wordt overschreven.

Optionele opmerkingen:
Je schrijft "getal2=0", dit heeft echter weinig nut. Je kunt even goed jezelf de twee extra tekens besparen en gewoon "getal2" schrijven.
De expressie "invoerbestand != NULL" kun je evengoed schrijven als "invoerbestand". De eerste expressie wilt eigenlijk gewoon zeggen "als invoerbestand waar is" ( "waar" is in de informatica een andere waarde als 0 ), maar is omslachtig geschreven. De tweede expressie wilt hetzelfde zeggen, maar is simpeler geschreven.
Bij je "if" statement stond je accolade niet helemaal recht onder het "if" statement, maak er een gewoonte van om oftewel de accolade op dezelfde regel als het "if" statement, of recht onder de "i" van "if" te zetten, of zoals in die aard bij andere conditionele statements. Anders kan de C compiler misschien eens in de war geraken als je een groot aantal geneste, conditionele statements hebt.
Na het "else" statement plaatste je direct de instructie, maar het is netter om daarna, als je geen accolades gebruikt, in te springen. Omdat anders, zoals al eerder gezegd, de C compiler in de war kan raken.

Een versie van jouw programma die hier allemaal mee rekening houdt:
#include <stdio.h>
#define max 10
#define filename "som.txt"

unsigned short multi ( unsigned char getal_a, unsigned chargetal_b )
{
    return getal_a * getal_b;
}

int main ( void )
{
    FILE *invoerbestand;
    unsigned char getal1 = 10, getal2 = 0, i;
    unsigned short som;
    invoerbestand = fopen ( filename, "a" );
    if ( invoerbestand )
    {
        for( i = 0; i <= max; i++)
        {
            som = multi(getal1, getal2);
            fprintf(invoerbestand, som);
            getal2++;
        }
        else
            printf("Het bestand %s kon niet worden gecreerd\n", invoerbestand);
    }

   return 0;
}

Ik hoop dat je aan al mijn uitleg wat hebt. Nog veel succes met C!

Offline xellos

  • Lid
Re: segmentation fault in c programma
« Reactie #3 Gepost op: 2010/01/19, 18:43:11 »
hartelijk bedankt voor de reacties hier kan ik mee veder!!!!

ik heb inderdaad wat domme fouten in mijn code staan maar begin dan ook net.

Offline Joshua822

  • Lid
Re: segmentation fault in c programma
« Reactie #4 Gepost op: 2010/01/19, 18:47:02 »
Citaat
ik heb inderdaad wat domme fouten in mijn code staan maar begin dan ook net.

Geen zorgen. Oefening baart kunst. Voor je het weet schrijf je C net alsof het Nederlands voor je is ;)

En natuurlijk heb ik het graag gedaan. De leden hier hebben het ook voor mij gedaan toen ik begon met C, dus zie ik het toch als vanzelfsprekend dat ik andere beginners ( ik ben zelf ook nog maar een beginner, na een driekwart jaartje C, om eerlijk te zijn :) ) ook help op hun pad naar het schrijven van goede C programma's !

-edit-

Ik zie trouwens net dat ik ook de format specifier bij de functie "fprintf" vergeten ben, dit is de goede broncode:
#include <stdio.h>
#define max 10
#define filename "som.txt"

unsigned short multi ( unsigned char getal_a, unsigned chargetal_b )
{
    return getal_a * getal_b;
}

int main ( void )
{
    FILE *invoerbestand;
    unsigned char getal1 = 10, getal2 = 0, i;
    unsigned short som;
    invoerbestand = fopen ( filename, "a" );
    if ( invoerbestand )
    {
        for( i = 0; i <= max; i++)
        {
            som = multi(getal1, getal2);
            fprintf(invoerbestand, "%hu", som);
            getal2++;
        }
        else
            printf("Het bestand %s kon niet worden gecreerd\n", invoerbestand);
    }

   return 0;
}

Zo, dat werkt :)
« Laatst bewerkt op: 2010/01/19, 18:50:13 door Joshua822 »

Offline xellos

  • Lid
Re: segmentation fault in c programma
« Reactie #5 Gepost op: 2010/01/19, 19:03:52 »
waar staat dat %hu voor dan?
in de tut die ik volg staat daar niks over http://wiki.nedlinux.nl/index.php?page=Basiscursus+C
kun je me daar wat meer over vertellen?

Offline Joshua822

  • Lid
Re: segmentation fault in c programma
« Reactie #6 Gepost op: 2010/01/19, 19:43:00 »
"%hu" is de format specifier voor een unsigned short variabel. Het is een beetje zoals de "%d" format specifier die je waarschijnlijk gewend bent om te geven aan de functie "printf", om aan te geven dat je een integer variabel op het scherm wilt laten zien.

Geen zorgen, je tutorial is goed. Ze willen gewoon de leerstof wat verminderen, voor absolute beginners. Dat is in principe goed. Maar toch kun je best nu al leren over het opslaan van kleine getallen in char en short variabelen. Dat is niet anders als het gebruik maken van integer variabelen, maar in functies als "printf" en "scanf" moet je gewoon een andere format specifier ( dit is het eerste argument van deze twee functies ) meegeven.

Type variabelFormat specifier
Short%h
Unsigned short%hu
Char%c
Unsigned char%uc

Offline xellos

  • Lid
Re: segmentation fault in c programma
« Reactie #7 Gepost op: 2010/01/19, 19:47:10 »
ah ik snap hem XD

Re: segmentation fault in c programma
« Reactie #8 Gepost op: 2010/01/19, 20:17:42 »
Nog even een kleine opmerking: een goede compiler plaatst een const-variabele ook niet in het RAM. Met een variabele heb je bovendien het voordeel van lexicale context (dat wil zeggen dat je het alleen kan gebruiken binnen de functie waar je hem gezet hebt en enkel op plaatsen waar een variabele mag voorkomen), wat je niet hebt met #defines. Over het algemeen worden voor constanten dus const-variabelen aangeraden ipv #defines.
I use a Unix-based system, that means I'll get laid as often as I have to reboot.
LibSylph
SeySayux.net

Offline Joshua822

  • Lid
Re: segmentation fault in c programma
« Reactie #9 Gepost op: 2010/01/19, 20:52:28 »
Citaat
Over het algemeen worden voor constanten dus const-variabelen aangeraden ipv #defines.

Daar kun je over discussiƫren. Als een variabel zichtbaar is, wil dit nog niet zeggen dat je hem hoeft te gebruiken. Eigenlijk maakt dit dus niet uit, als je maar voorzichtig programmeert.

En dan nog, het is niet zo dat de gebruiker met de broncode interactie zal hebben, de gebruiker heeft interactie met het uiteindelijke programma. En dat uiteindelijke programma moet jij als programmeur net hebben geprogrammeerd.