Читатели — писатель: Ошибка сегментации Переполнение стека

Итак, у меня есть небольшая программа, которая имитирует веб-камеру. Таким образом, кадры (в моей программе значения данных) должны быть сохранены в 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;
}

Кто-нибудь знает, где моя вина, где-то тупик, я думаю, но я не могу понять, где.

-1

Решение

Я не знаю, является ли это вашей ошибкой, или это другая ошибка, но … когда вы пишете 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 .: извините за мой плохой английский

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]