Op deze website gebruiken we cookies om content en advertenties te personaliseren, om functies voor social media te bieden en om ons websiteverkeer te analyseren. Ook delen we informatie over uw gebruik van onze site met onze partners voor social media, adverteren en analyse. Deze partners kunnen deze gegevens combineren met andere informatie die u aan ze heeft verstrekt of die ze hebben verzameld op basis van uw gebruik van hun services. Meer informatie.

Akkoord

Vraag & Antwoord

Programmeren

[C++ :: IO] Zwaar in de shit :cry:

None
10 antwoorden
  • :cry: Ik heb ineens in zwaar weirds, ik dacht net dat alles werkte maar nee….
    Oke het is nogal veel maar eerst post ik ff AL m'n code:

    pio.h
    [code:1:46fd5d7a66]
    #include <unistd.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/time.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <iostream.h>

    #ifndef _PIO_H
    #define _PIO_H

    class pStream
    {
    public:
    pStream() { _fdnum++; }
    ~pStream() { _fdnum–; }
    int fd;
    int putCh(char);
    char getCh();
    char* fetchData(int);
    int writeData(char *);
    virtual int open() = 0;
    void close();
    virtual bool eof() = 0;
    bool wait(int timeout = 0);
    const int fdnum() { return _fdnum; }
    private:
    static unsigned int _fdnum;
    };

    /** Implentation of standard low-level file-IO
    */
    class pFile : public pStream
    {
    public:
    //int fd;
    int open(char *filename, int mode);
    void close();
    private:
    };

    class pIOMode
    {
    public:

    enum PIO_MODE
    {
    READ = O_RDONLY,
    WRITE = O_WRONLY | O_CREAT | O_TRUNC,
    APPEND = O_APPEND,
    READWRITE = O_RDWR,
    NEWREADWRITE = O_RDWR | O_CREAT,
    NEWAPPEND = O_APPEND | O_CREAT,
    BINAIRY_READ,
    BINAIRY_WRITE,
    BINAIRY_APPEND,
    BINAIRY_READWRITE,
    BINAIRY_NEWREADWRITE,
    BINAIRY_NEWAPPEND
    };
    static const char *IOMode(PIO_MODE);
    static const char *IOMode(int);
    };

    /*class pFilename
    {
    public:
    pFilename(char *);
    pFilename();
    ~pFilename();
    private:
    };*/

    #endif

    [/code:1:46fd5d7a66]

    pio.cpp (het belangrijkste deel)
    [code:1:46fd5d7a66]#include "pio.h"

    char pStream::getCh() // Get one character
    {
    char ch;
    read(fd, &ch, 1);
    return ch;
    }

    int pStream::putCh(char ch) // Put one character
    {
    return write(fd, &ch, 1);
    }

    int pStream::writeData(char *buffer)
    {
    int readLength =1;
    int buffPos =0;
    while((buffPos < strlen(buffer)) && (!(readLength < 1)))
    {
    readLength = write(fd, buffer+buffPos, strlen(buffer) - buffPos);
    buffPos += readLength;
    }

    return buffPos;

    }

    char* pStream::fetchData( int length)
    {

    int readLength =1;
    int buffPos =0;
    char *buffer;
    while((buffPos < length) && (!(readLength < 1)))
    {
    readLength = read(fd, buffer+buffPos, length - buffPos);
    buffPos += readLength;
    }

    return buffer;

    }

    bool pStream::wait(int timeout) // Wait for the filediscriptor to become ready
    {
    fd_set waitfd;
    FD_ZERO(&waitfd);
    FD_SET(fd, &waitfd);
    int result;
    struct timeval waittimeout;
    waittimeout.tv_sec = 0;
    waittimeout.tv_usec = timeout * 1000;
    result = select(FD_SETSIZE, &waitfd, NULL, NULL, &waittimeout);

    switch(result){
    case 0: // timeout
    return false;
    case -1: // error
    cerr << "Plib::pStream::wait::Select error!
    ";
    return false;
    default: // fd ready
    return true;
    }
    return false; // Actualy, we never reach this return, just to make gcc happy ;)
    }

    ///////

    int pFile::open(char *filename, int mode)
    {
    if((fd = ::open(filename, mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) // More structural construction needed!!! help!
    return 1;
    else
    return -1;
    }

    void pFile::close()
    {
    ::close(fd);
    }

    [/code:1:46fd5d7a66]

    het test proggie (test.cpp)
    [code:1:46fd5d7a66]
    #include "pio.h"
    #include <stdio.h>

    main(){
    pFile *fin;
    pFile *fout;

    fin->open("testfile", pIOMode::READ);
    fout->open("lowtest.out", pIOMode::WRITE);

    }
    [/code:1:46fd5d7a66]

    de error:
    [code:1:46fd5d7a66]
    $gcc -o test test.cpp -L. -lplan
    $export LD_LIBRARY_PATH=$PWD
    $./test
    Segfault :cry:
    $
    [/code:1:46fd5d7a66]

    Als ik um maar met 1 filestream compileer (maakt niet welke) doe ie het wel:

    [code:1:46fd5d7a66]
    #include "pio.h"
    #include <stdio.h>

    main(){
    pFile *fin;
    // pFile *fout;

    fin->open("testfile", pIOMode::READ);
    // fout->open("lowtest.out", pIOMode::WRITE);

    }
    [/code:1:46fd5d7a66]

    $./test
    $

    Ik heb alles al zowat geprobeerd, maar nix werkt…..
    :cry: :cry:

    Heel erg bedankt,
    Barry
  • Oke hier ben ik net achter gekomen:
    Als ik alle virual functions uit pStream haal en in het test proggie geen pointers naar pFile defineer, werkt ut wel:
    pFile fout;
    ipv pFile *fout;

    Zo krijg ik dus geen segfault, maar ligt dit nu aan? en kan ik het verhelpen??

    Thnx,
    Barry
  • Ik heb je code niet gelzen, veel te veel :D en ik ben lui in de vakantie, maarreh door virtual functions ga je gebruik maken van late / dynamic binding.

    Is dat de bedoeling?
  • Wacht ff, ik snap ff niet wat je bedoelt….
  • Ik heb een leuk voorbeeld en ik heb al zo'n idee waar je de fout bent ingegaan. Moet je ff 2 daagjes w8 en want ik heb mijn C++ boek niet bij de hand.
  • Ik wacht geduldig ;)
  • Oke 2 daagjes verder ;)
  • Ok Phaas, je beloofde antwoord:

    Het idee van virtual functions is als volgt:

    Bekijk de volgende regels code:

    [code:1:5bb100094e]
    int main()
    {
    dier *p[1];
    p[0] = new vis();
    p[1] = new vogel();

    return 0;

    }
    [/code:1:5bb100094e]

    Hierbij horen de volgende klasses:

    [code:1:5bb100094e]
    class dier //basisklasse
    {
    };

    class vis: public dier
    {
    }; //afgeleide klasse

    class vogel: public dier
    {
    };

    [/code:1:5bb100094e]

    Ok, de elementen vam array p bevat pointers. De declaratie impliceert dat de de pointers in de array gaan wijzen naar de basisklasse dier. Echter p[0] en p[1] wijzen naar een afgeleide klasse, vis en vogel.

    Stel dat ze allemaal een eigen print-functie hebben. dan zou je ze zo kunnen aanroepen:
    [code:1:5bb100094e]
    vogel v();
    v.print();
    [/code:1:5bb100094e]

    Ok, maar dit hebben we niet. Wij doen het volgende:

    [code:1:5bb100094e]
    p[1]->print();
    [/code:1:5bb100094e]

    We kennen echter 2 fases bij de verwerking van ons programma. de uitvoeringsfase en de compileerfase. De C++ compiler weet nu tijdens de compileerfase niet welke print hij moet aanroepen. v was het afgeleide type vogel, maar p[1] is gedeclareerd als een pointer naar het basistype dier. p[1] zal nu niet automatisch de print van vogel aanroepen.

    Hoe zorgen we ervoor dat wel de print functie van vogel aangeroepen wordt? Door bij de printfunctie het keyword [i:5bb100094e]virtual[/i:5bb100094e] neer te zetten. Er wordt nu een stukje informatie bewaard die aangeeft dat het object tot die specifieke afgeleide klasse behoort. Nu wordt tijdens het uitvoeren pas bepaald dat de print van vogel moet worden aangeroepen. Dit noemen we late binding.

    Zo en vis nu eens uit waardoor je progje het wel deed als je alle virtual functies wegliet. Waarschijnlijk wijsde hij naar een afgeleide klasse of functie die tijdens de uitvoeringsfase niet bestond of iest dergelijks.

    Ik ga nu maffen!
  • [code:1:6af8b8f8cf]
    #include "pio.h"
    #include <stdio.h>

    main(){
    pFile *fin;
    pFile *fout;

    fin->open("testfile", pIOMode::READ);
    fout->open("lowtest.out", pIOMode::WRITE);

    }

    [/code:1:6af8b8f8cf]

    nou… dit ziet 'r op de eerste plaats al FOUT uit. je maakt 2 niet geinitialiseerde pointers met de namen fin en fout, en gebruikt ze dan. Eigenlijk zou je een null pointer exception moeten hebben gehad, maar zo'n geluk had je dus niet.

    Waar je wel last van had, precies hierdoor, is dat je een functie aanroept op een object dat niet bestaat, op een lokatie die je niet hebt gereserveerd. Als die functie virtueel is moet hij runtime uitvogelen welk object 't is, en zoekt ie dus in die trash (99%+ kans op segfault) naar het type van die functie. Had er iets gestaan dat wees op een ander type object zou je een pure virtual function call hebben gedaan, en zou ie daarmee zijn gecrasht. Door puur toeval zou je nog goed terecht kunnen komen, maar dan nog is dit extreem slordig geprogrammeerd.

    [code:1:6af8b8f8cf]
    #include "pio.h"
    #include <stdio.h>

    main(){
    pFile *fin = new pFile();
    pFile *fout = new pFile();

    fin->open("testfile", pIOMode::READ);
    fout->open("lowtest.out", pIOMode::WRITE);

    }

    [/code:1:6af8b8f8cf]

    ps, mag ik vragen waar je eigenlijk mee bezig bent? deze classes zijn standaard gedefinieerd dus behalve als je geinteresseerd bent in de implementatie, of de standaard niet kunt/wil gebruiken, snap ik je niet.
  • Hoi candyman,

    Ik ben bezig met een network library, die stream functies horen daar dus ook bij. En ik wilde meteen ook naar dat file gebeuren kijken, de nieuwe versie gaat iig ook buffering enzo ondersteunen.

    En w.roosenburg; onwijs bedankt voor je antwoord, ik geloof dat ik ut nu weer een beetje snap ;)

    Barry

Beantwoord deze vraag

Dit is een gearchiveerde pagina. Antwoorden is niet meer mogelijk.