2016-04-09 1 views
-1

J'ai donc un petit programme qui simule une webcam. Donc les images (dans mon programme la valeur des données) doivent être sauvegardées dans 2 fichiers et à l'écran. Mais quand je cours mon code j'obtiens une faute de segmentation;Readers - writer: Segmentation fault C++

#include <iostream> 
#include <fstream> 
#include <pthread.h> 
#include <stdlib.h> 
#include <windows.h> 
#include <winbase.h> 

#ifdef WIN32 
# include <process.h> 
#else 
# include <time.h> 
#endif 

static void Error(const char *str) 
{ 
    std::cerr << str << std::endl; 
    exit(0); 
} 
class Data 
{ 
public: 
    Data() : refcount(0), value(0) {} 
    void ref() { refcount++; } 
    void unref() { refcount--; } 
    bool isUnused(){ return (refcount == 0); } 
    void setValue(int val){ value = val; } 
    void print(std::ostream &ostr) { ostr << value << std::endl; } 

private: 
    unsigned int refcount; 
    int value; 
}; 

class Buffer 
{ 
public: 
    Buffer() : lastProduced(0) {} 

public: 
    Data *getEmptyDataElement() 
    { 
     Data *d = 0; /* = empty data element */; 
     for (int i=0; i<BUFFERSIZE; i++) 
     { 
      if (storage[i].isUnused()) { 
       d = &storage[i]; 
       break; 
      } 
     } 

     return d; 
    } 

    Data *getLastProducedData(Data* previous) 
    { 
     // check if new element is available 
     Data *d = lastProduced; 
     d->ref(); 
     return d; 
    } 

    void publish(Data *d) /* update last produced, so getLastProducedData returns the correct element */ 
    { 
     lastProduced = d; 
    } 

    void release(Data *d) /* update handled element, to make it available via getEmptyDataElement */ 
    { 
     d->unref(); 
    } 

private: 
    static const int BUFFERSIZE = 10; 
    Data storage[BUFFERSIZE]; 
    Data *lastProduced; 
}; 

static void *start_thread(void *t); 
class Thread 
{ 
public: 
    Thread() : tid(0) {} 

    void start() 
    { 
     if(pthread_create(&tid, 0, start_thread, (void *) this) != 0) 
      Error("Error: failed to create thread"); 
    } 

    void wait() 
    { 
     void *status; 
     pthread_join(tid, &status); 
    } 

    static void sleep(unsigned int msecs) 
    { 
#ifdef WIN32 
     if(SleepEx(msecs, TRUE) != 0) 
      Error("Error: SleepEx interrupted"); 
#else 
     struct timespec timeout; // timeout value for wait function 

     // prepare timeout value 
     timeout.tv_sec = msecs/1000; 
     msecs -= timeout.tv_sec * 1000; 
     timeout.tv_nsec = (1000 * msecs) * 1000; 

     if(nanosleep(&timeout, 0) != 0) 
      Error("Error: nanosleep interrupted or failed"); 
#endif 
    } 

    virtual void run() = 0; 

private: 
    pthread_t tid; 
}; 

static void *start_thread(void *t) 
{ 
    reinterpret_cast<Thread *>(t)->run(); 
    return 0; 
} 

class Producer : public Thread 
{ 
public: 
    Producer(Buffer &b, long sequenceNumber) : buffer(b), sequenceNumber(sequenceNumber) {} 

private: 
    void run() 
    { 
     for(int i = 0; i < 1000; ++i) 
     { 
      Data *d = buffer.getEmptyDataElement(); 
      produceData(d); 
      buffer.publish(d); 
     } 
    } 

    void produceData(Data *d) 
    { 
     Thread::sleep((float(rand())/RAND_MAX) * 1000); // sleep between 0 and 1 sec 
     d->setValue(sequenceNumber++); 
     d->print(std::cout); 
    } 

    Buffer &buffer; 
    long sequenceNumber; 
}; 


class Handler : public Thread 
{ 
public: 
    Handler(Buffer &b, std::ostream &ostr) : buffer(b), ostr(ostr) {} 

private: 
    void run() 
    { 
     Data *previous = 0; 
     while(1) 
     { 
      Data *d = buffer.getLastProducedData(previous); 
      handleData(d); 
      buffer.release(d); 
      previous = d; 
     } 
    } 
    void handleData(Data *d) 
    { 
     d->print(ostr); 
     Thread::sleep((float(rand())/RAND_MAX) * 1000); // sleep between 0 and 1 sec 
    } 

    Buffer &buffer; 
    std::ostream &ostr; 
}; 

int main() 
{ 
    Buffer buff; 

    std::ofstream file1; 
    std::ofstream file2; 

    file1.open ("file1.txt"); 
    file2.open ("file2.txt"); 
    // open the files 

    Producer p(buff, 0); 
    Handler h1(buff, std::cout), h2(buff, file1), h3(buff, file2); 

    p.start(); 
    h1.start(); 
    h2.start(); 
    h3.start(); 

    p.wait(); 
    h1.wait(); 
    h2.wait(); 
    h3.wait(); 
    // wait until producers stopped producing and handlers handled all produced data 

    return EXIT_SUCCESS; 
} 

Est-ce que quelqu'un sait où est ma faute, quelque part il y a une impasse, je pense, mais je ne peux pas savoir où.

+0

Créer un [mcve] – user2079303

Répondre

0

Je ne sais pas si c'est la faute que vous cherchez ou si elle est une autre faute, mais ... quand vous écrivez votre Buffer::getEmptyDataElement() de cette façon

Data *getEmptyDataElement() 
{ 
    Data *d = 0; /* = empty data element */; 
    for (int i=0; i<BUFFERSIZE; i++) 
    { 
     if (storage[i].isUnused()) { 
      d = &storage[i]; 
      break; 
     } 
    } 

    return d; 
} 

vous écrire une fonction qui peut renvoyer une NULLData pointeur (lorsque tous les stockages sont utilisés).

Cela peut être bon si vous testez le pointeur retourné avant de l'utiliser, mais, dans Producer::run()

void run() 
{ 
    for(int i = 0; i < 1000; ++i) 
    { 
     Data *d = buffer.getEmptyDataElement(); 
     produceData(d); 
     buffer.publish(d); 
    } 
} 

vous passez le pointeur d-Producer::produceData() sans le tester et

void produceData(Data *d) 
{ 
    Thread::sleep((float(rand())/RAND_MAX) * 1000); // sleep between 0 and 1 sec 
    d->setValue(sequenceNumber++); // what if 'd' is NULL? 
    d->print(std::cout);   // what if 'd' is NULL? 
} 

Producer::produceData() utiliser sans test si c'est NULL.

Panne potentielle.

problème potentiel Même avec Buffer::getLastProducedData() qui utilise lastProduced (qui peut être NULL reçue par publish() par valeur non testée de Producer::run() si Producer::produceData() test de la valeur?) Sans le tester

Data *getLastProducedData(Data* previous) 
{ 
    // check if new element is available 
    Data *d = lastProduced; 
    d->ref(); // what if 'lastProduced' (and so 'd') is NULL? 
    return d; 
} 

Quoi qu'il en soit: vous devriez nous donner file1.txt et file2.txt si vous voulez que nous puissions sauvegarder votre programme.

P.: désolé pour mon mauvais anglais