2016-04-09 14 views
-1

Also habe ich ein kleines Programm, das eine Webcam simuliert. Also müssen die Frames (in meinem Programm der Wert der Daten) in 2 Dateien und auf dem Bildschirm gespeichert werden. Aber wenn ich meinen Code ausführe, bekomme ich einen Segmentierungsfehler;Readers - Writer: Segmentierungsfehler 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; 
} 

Weiß jemand, wo mein Fehler ist, irgendwo da ein Deadlock ich denke, aber ich kann nicht herausfinden, wo.

+0

Erstellen Sie ein [mcve] – user2079303

Antwort

0

Ich weiß nicht, ob es die Schuld für Sie suchen, oder wenn es ein anderer Fehler ist, aber ... wenn Sie Ihre Buffer::getEmptyDataElement() auf diese Weise schreiben

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; 
} 

Sie eine Funktion schreiben, die eine zurückkehren NULLData Zeiger (wenn alle Speicher verwendet werden).

Das kann gut sein, wenn Sie den Zeiger zurück zu testen, bevor es zu benutzen, aber in Producer::run()

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

geben Sie die d Zeiger auf Producer::produceData() ohne es zu testen und

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() es verwenden ohne zu testen, wenn es NULL ist.

Möglicher Absturz.

Gleiche mögliches Problem mit Buffer::getLastProducedData() die lastProduced verwendet (? Das kann durch publish() über nicht getestet Wert von Producer::run() wenn Producer::produceData() Test der Wert NULL empfangen sein?), Ohne es zu testen

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; 
} 

Wie dem auch sei: Sie sollten uns geben file1.txt und file2.txt Wenn Sie möchten, können wir Ihr Programm testen.

P .: Entschuldigung für mein schlechtes Englisch