Итак, у меня есть небольшая программа, которая имитирует веб-камеру. Таким образом, кадры (в моей программе значения данных) должны быть сохранены в 2 файла и на экране Но когда я запускаю свой код, я получаю ошибку сегментации;
#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;
}
Кто-нибудь знает, где моя вина, где-то тупик, я думаю, но я не могу понять, где.
Я не знаю, является ли это вашей ошибкой, или это другая ошибка, но … когда вы пишете Buffer::getEmptyDataElement()
в этом случае
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;
}
вы пишете функцию, которая может вернуть NULL
Data
указатель (когда все хранилища используются).
Это может быть хорошо, если вы тестируете указатель, возвращенный ранее, чтобы использовать его, но в Producer::run()
void run()
{
for(int i = 0; i < 1000; ++i)
{
Data *d = buffer.getEmptyDataElement();
produceData(d);
buffer.publish(d);
}
}
Вы передаете d
указатель на Producer::produceData()
без тестирования этого и
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()
используйте его без тестирования, если это NULL
,
Потенциальная авария.
Та же потенциальная проблема с Buffer::getLastProducedData()
который использует lastProduced
(это может быть NULL
? получил publish()
через не проверенное значение из Producer::run()
если Producer::produceData()
проверить значение?) без проверки
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;
}
Во всяком случае: вы должны дать нам file1.txt
а также file2.txt
если вы хотите, мы можем попробовать вашу программу.
P.s .: извините за мой плохой английский
Других решений пока нет …