RingBuffer for data collection - c++

I have a Ring Buffer implementation that I like to use to process an incoming data. Is the following approach safe and efficient to use considering synchronizations needed?.
void CMyDlg::MyButton1()
{
RingBuffer BufRing(10000);
unsigned char InputBuf[100];
unsigned char OutBuf[100];
for (int ii = 0; ii < 1000; ++ii)
{
for (int i = 0; i < 100; ++i)
{
InputBuf[i] = i;
}
BufRing.Write(InputBuf,100);
BufRing.Read(OutBuf,100);
AfxBeginThread(WorkerThreadProc,OutBuf,THREAD_PRIORITY_NORMAL,0,0,NULL);
}
}
UINT WorkerThreadProc( LPVOID Param )
{
unsigned char* pThreadBuf = (unsigned char*)Param;
for (int c = 0; c < 100; ++c)
{
TRACE("Loop %d elemnt %x\n",c,pThreadBuf[c]);
}
return TRUE;
}

Looks hazardous to me...
void CMyDlg::MyButton1()
{
// ...
unsigned char OutBuf[100];
for (int ii = 0; ii < 1000; ++ii)
{
// ...
BufRing.Read(OutBuf,100);
AfxBeginThread(WorkerThreadProc,OutBuf,THREAD_PRIORITY_NORMAL,0,0,NULL);
}
}
The problem that I see is that you're using a single buffer (OutBuf) to store data in, passing it to a worker thread, and then modifying that same buffer in the next iteration of your loop.
Your test code won't reveal this, because you're simply repopulating OutBuf with the same values in every iteration (as far as I can tell, anyway). If you changed InputBuf[i] = i; to InputBuf[i] = ii; and included a unique thread ID in your TRACE output, you'd probably see suspicious behaviour.

Related

Allocating pointer to a pointer

I have 5 buffers and 20 frames to write in them. Being one frame per buffer, at a certain moment i will have to overwrite buffers with the newest frame.
At random moments i need to read the oldest frame(its id and data) from all the buffers.
I am obliged to use a pointer to a pointer for my buffers, but since i suck at pointers, not even the allocation works, giving me a SEGMENTATION FAULT and not sure why.
What i have until now:
void fakeFrame(uint16_t *data)
{
for (auto i = 0; i < 1440; i++)
for (auto j = 0; j < 1440; j++)
data[(i * 1440) + j] = std::rand()%2;
}
int main()
{
uint16_t **p_frameBuffers;
uint32_t *p_frameIdxs;
uint16_t wrIdx = 0;
uint16_t reIdx = 0;
uint16_t currentFrameCounter = 0;
uint16_t nbBuffers = 5;
for(auto i =0; i< nbBuffers; i++)
{
p_frameBuffers[i] = (uint16_t*)malloc(1440*1440*2);
}
while(currentFrameCounter <= 20)
{
wrIdx++;
wrIdx %= nbBuffers;
if(wrIdx == reIdx)
{
std::cout<<"i passed the limit";
}
currentFrameCounter++;
p_frameIdxs[wrIdx] = currentFrameCounter;
fakeFrame(p_frameBuffers[wrIdx]);
}
std::cout<<"\n";
return 0;
}
I can see a few different problems with this code here.
You declare the long-form of the function for fakeFrame() in the beginning of the program, when the standard is usually to declare the function header first.
This is like a warning to the program that a function is about to be used, and that it's not part of a class or anything. Just standalone.
Example:
#include <iostream>
void fakeFrame();
int main()
{
return 0;
}
void fakeFrame()
{
for (auto i = 0; i < 1440; i++)
for (auto j = 0; j < 1440; j++)
data[(i * 1440) + j] = std::rand()%2;
}
You're also using some of these 16 and 32 bit unsigned ints as if they were arrays, so I was deeply confused about that. Did you mean to set them as arrays?
You also have some variables being declared in a non-array context but being used as arrays. I'm not deeply familiar with the uint variable/object types but I know they aren't usually meant to function as standalone arrays.
Also, no variable called m_pFrameBuffers is actually declared in the code you provided. Plus this is also used as an array, so it should really be declared as one.
I hope this provides at least some insight into what's not working. I'm actually kind of surprised that the void function ran before, it's improperly formatted.
In the end this is what did it: the pointer to a pointer is actually an array of pointers (which i did not know, of course)
p_frameBuffers = (uint16_t**)malloc((sizeof(uint16_t*)*nbBuffers));
for(auto i = 0; i < nbBuffers; i++)
{
p_frameBuffers[i] = (uint16_t*)malloc(1440*1440*2);
}

C++, How to pass 2 dimension Vector array to function

I am studying the vector array with my assignment, and with this assignment I have some question that is about the two dimension vector array.
THE ASSIGNMENT is : List the current process with show up their parent-child relation.
Question
I want to pass the vector value just ppids[i] to do this I write it only write
vector<process*>
If my function parameter declare like
vector<vector<process*>>
it must write "ppids" so it is not my intent.
Error
Cannot convert 1 parameter from 'std::vector<process *,std::allocator<_Ty>>'to 'std::vector &'
So, here is my codes. (Just a part of my code)
Struct Vector :
struct process {
string procName;
DWORD procPid;
DWORD procPpid;
};
main vector, get process information on msdn API
std::vector <process*> myProcess;
part of main below...
//
// Group Vector by PPid
//****(here is 2 dimension vector)****
std::vector< std::vector< process* > > ppids;
int n = 0;
int index = 1;
for (int i = 0, size = tempPid.size(); i < size; ++i) {
ppids.push_back(vector<process*>());
for (int j = 0, size2 = myProcess.size(); j < size2; ++j) {
if (myProcess[j]->procPpid == tempPid[i]) {
ppids[n].push_back(myProcess[j]);
};
}
for (int k = 0, size3 = ppids[n].size(); k < size3; ++k)
{
_tprintf(TEXT("%d \t"), index);
index++;
_tprintf(TEXT("[%s]"), ppids[n][k]->procName.c_str());
_tprintf(TEXT("[%d]"), ppids[n][k]->procPid);
_tprintf(TEXT("[%d] \n"), ppids[n][k]->procPpid);
}
n++;
}
myProcess.clear();
the function is called on here.
// Combine vector
myProcess = ppids[0];
std::vector <process*> tmpProcess;
for (int i = 1, size = ppids.size(); i < size; ++i) {
tmpProcess = combine(myProcess, ppids[i]);
myProcess.clear();
myProcess = tmpProcess;
}
and finally, this is my function.
vector<process*> combine(vector<process*> tempA, vector<process*> tempB) {
std::vector <process*> alloProcess;
for (int i = 0, size = tempA.size(); i < size; ++i) {
if (tempA[i]->procPid == tempB[1]->procPpid)
{
alloProcess.push_back(tempA[i]);
for (int j = 0, size2 = tempB.size(); j < size2; ++j) {
alloProcess.push_back(tempB[j]);
}
}
else {
alloProcess.push_back(tempB[i]);
}
}
return alloProcess;
}
Full codes on here:
https://gist.github.com/anonymous/25e636086bbfacbec78508736935d3af
void function(vector< vector<process> > *matrix)
Specifies a pointer, it is essentially passed by reference. However, in C++, it's better to avoid pointers and pass a reference directly:
void function(vector< vector<process> > &matrix)
and
function(matrix1); // Function call

Accessing dynamic 2D char array C++

In my class I've got:
private:
//...
char** mNumber;
//...
Then I initialize it in constructor:
PhoneBook::PhoneBook()
{
mNumber = NULL;
}
I also have method set default:
bool PhoneBook::setDefault()
{
lock();
//...
for (uint8 i = 0; i < 5; ++i)
{
mNumber[i] = new char[5];
for (uint8 k = 0; k < 4; ++k)
{
mNumber[i][k] = '0' + k;
}
mNumber[i][4] = '\0';
}
unlock();
return true;
}
In my program, when I want to write number (I can write up to five numbers), program should use method:
bool PhoneBook::write(DataOutputStream& s)
{
lock();
//...
unsigned long checksum = 0;
for (uint8 j = 0; j <5; j++)
{
unsigned short k = 0;
do
{
char number= mUserNo[j][k];
checksum += 0x000000FF & (number>> 8); //checksum is not problem here I guess
checksum += 0x000000FF & (number);
s.write_int8(userNo);
} while(mNumber[j][k++]=='\0');
}
s.write_uint32(checksum);
s.flush();
unlock();
return (s.ok());
}
It crashes at line:
char userNo = mUserNo[j][k];
It also do not set default values (they are not displayed in application window where they are supposed to be).
Visual Studio 2010 prompt:
Unhandled exception at 0x012b6fb8 (main_app.exe) in main_app: 0xC0000005: Access violation reading location 0xfdfdcdcd.
I've tried to debug it, but can't find out what's wrong. I can only guess that it's something wrong with 2d array, since I feel not so good with them and when I've tried something similiar with 1D, it worked fine.
Please help me with code and let better understand multiD arrays in c++.
BTW I'm not allowe to use std::string. Just no, I can't use it here.
You only ever set mNumber to NULL so any access to memory via mNumber, mNumber [j][k] for example, is most likely going to crash with an access violation (1). You need to initialise mNumber to be a meaningful value, by using new somewhere! Better still, use a standard container like std::vector:
// the declaration of mNumber, do not initialise mNumber to NULL!
std::vector <char *> mNumber; // only need one * here!
(1) This is the most common thing to happen on Windows and Linux, some (but not many) OSes/systems may silently let you do this!
if you need "char**" instead std::vector, you should to allocate memory for it before filling default values. Like this,
bool PhoneBook::setDefault()
{
........
mNumber = new char*[5]; // allocating memory for mNumber
for (uint8 i = 0; i < 5; ++i)
{
mNumber[i] = new char[4];
for (uint8 k = 0; k < 4; ++k)
{
mNumber[i][k] = '0' + k;
}
mNumber[i][4] = '\0';
}
unlock();
return true;
}

resize vector element of a struct - segv

I am trying to resize a vector element of a structure and it causes segv. But when I did it individually for some small struct it worked fine. I am curious to know how it allocates memory to structure in which there is a vector element that could be resized. The below comment line causes segv in first iteration (type_index = 0).
Structure:-
struct thread_data {
dbPointer_t pObj;
dbObjId_t objId;
dbObjTypeId_t type;
dbObjId_t topCellId;
dbIteratorId_t objsIterId;
int precision;
int64_t shape_objs;
vector<vector<vector<PL_trp_header_t *> > > ps_hdrs;
int pool;
int num_layers;
int to_cell_id;
};
Below is the snippet of code:-
thread_data *t_data[types_length];
for(int type_index=0; type_index < types_length; ++type_index) {
t_data[type_index] = (thread_data*)malloc(sizeof(thread_data));
t_data[type_index]->pObj = NULL;
t_data[type_index]->objId = objId;
t_data[type_index]->type = shape_types[type_index];
t_data[type_index]->topCellId = topCellId;
t_data[type_index]->objsIterId = objsIterId;
t_data[type_index]->precision = nparams.unit_precision;
t_data[type_index]->shape_objs = 0;
t_data[type_index]->ps_hdrs.resize(num_layers); //this line causes segv
t_data[type_index]->pool = pool;
t_data[type_index]->num_layers = num_layers;
t_data[type_index]->to_cell_id = tocell_id;
for (int num = 0; num < num_layers; num++) {
t_data[type_index]->ps_hdrs[num].resize(index_limit);
for (int rows = 0; rows < index_limit; rows++)
t_data[type_index]->ps_hdrs[num][rows].resize(index_limit);
}
for(int i = 0; i < num_layers; i++) {
for (int rows = 0; rows < index_limit; rows++) {
for (int cols = 0; cols < index_limit; cols++) {
t_data[type_index]->ps_hdrs[i][rows][cols] = alloc_hdr(pool);
}
}
}
printf("In main: creating thread %d \n", type_index);
rc_thread = pthread_create(&threads[type_index], NULL, thread_fn, (void *) &t_data[type_index]);
if (rc_thread){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
free(t_data[type_index]);
}
I think you are allocating your data with malloc. In this case no constructors for your objects and theier members are called. This works with PODs but not with classes like vector. In the line with the error you try to access some unitialised memory like an vector. Try new and delete instead of mallac and free to solve this isue.

fwrite, fread - problems with fread

I have following code:
int main()
{
char* pedal[20];
char* pedal2[20];
for (int i = 0; i < 20; i++)
{
pedal[i] = "Pedal";
}
FILE* plik;
plik = fopen("teraz.txt","wb");
for (int i = 0; i < 20; i++)
{
fwrite(pedal[i],strlen(pedal[i]),1,plik);
}
system("pause");
fclose(plik);
plik = fopen("teraz.txt","rb");
for (int i = 0; i < 20; i++)
{
fread(pedal2[i],5,1,plik); //I know for now that every element has 5 bytes
}
for (int i = 0; i < 20; i++)
{
std::cout << pedal2[i] << std::endl;
}
fclose(plik);
system("pause");
return 0;
}
It's crashing at reading and second question let's assume that I have structure where I keep like integers, floats and also char* array and how can I easly write whole structure to the file? Normal fwrite with sizeof structure is not working
Your problem that you didn't allocate buffer for reading. In fact line
fread(pedal2[i],5,1,plik)
reads to unknown place. You need allocate memory (in your case it is 5 + 1 bytes for zero terminated string).
pedal2[i] = malloc(5+1);
fread(pedal2[i],5,1,plik)
Don't forget to release it after usage.
You can't read into pedal2 without first having allocated space for it.
You need something like this:
for (int i = 0; i < 20; ++i) {
pedal[i] = malloc(100); //allocate some space
}
Your first question seem to have already been answered by Simone & Dewfy.
For your second question about how to write structure values into the file, you will have to write member by member.
Please check fprintf. You can probably use it for writing different data types.