I am writing a C++ program (see below). My goal is to store data in iov struct. I have allocated buffer of fixed length in constructor. Every time that buffer gets filled, I want to transfer data in iov and allocated new buffer of fixed length. Finally when done with data processing, I want to return iov struct. My intension here is to store all these data into iov so that if it's required in future, I can send data easily. I have written sample code. But it seems it's not working. I got an "Bus error: 10". Can someone help me?
Sample code:
#include <iostream>
#include <string>
#include <sys/uio.h>
#include <cstdlib>
using namespace std;
#define MAX_LEN 1000
#define MIN_LEN 20
class MyClass
{
public:
MyClass();
~MyClass();
void fillData(std::string &data);
private:
struct iovec *iov;
unsigned int count;
unsigned int len;
char *buf;
unsigned int total_len;
unsigned int tmp_len;
};
MyClass::MyClass()
{
cout << "Inside constructor" << endl;
total_len = MIN_LEN;
buf = (char *)malloc(MAX_LEN);
if (buf == NULL) {
cout << "Error: can’t allocate buf" << endl;
exit(EXIT_FAILURE);
}
}
MyClass::~MyClass()
{
free(buf);
}
void MyClass::fillData(std::string &data)
{
unsigned int d_len, tmp_len, offset;
d_len = data.size();
const char* t = data.c_str();
total_len += d_len;
tmp_len += d_len;
if (total_len > MAX_LEN) {
/* Allocate memory and assign to iov */
tmp_len = d_len;
}
memcpy(buf + offset, t, d_len);
/* Adjust offset */
}
int main()
{
MyClass my_obj;
int i;
std::string str = "Hey, welcome to my first class!";
for (i = 0; i < 10; i++) {
my_obj.fillData(str);
}
return 0;
}
Without understanding the intent of your program in detail, it is very clear that you forgot to reserve memory for the iov-objects themselfes.
For example, in your constructor you write iov[0].iov_base = buf, yet iov has not been allocated before.
To overcome this, somewhere in your code, before the first access to iov, you should write something like iov = calloc(100,sizeof(struct iovev)) or a c++ equivalent using new[].
Consider the following program:
struct myStruct {
char *buf;
int len;
};
int main() {
struct myStruct *myStructPtr;
myStructPtr->buf = "Herbert"; // Illegal, since myStructPtr is not initialized; So even if "Herbert" is valid, there is no place to store the pointer to literal "Herbert".
myStructPtr[0].buf = "Herbert"; // Illegal, since myStructPtr is not initialized
// but:
struct myStruct *myStructObj = new (struct myStruct);
myStructObj->buf = "Herbert"; // OK, because myStructObj can store the pointer to literal "Herbert"
myStructObj->buf = "Something else"; // OK; myStructObj can hold a pointer, so just let it point to a different portion of memory. No need for an extra "new (struct myStruct)" here
}
I took your code, which didn't exactly use anything with the iovec, and I modified it a little.
I am not sure why developers prefer buffers of char* instead of std::string
or why use a pointer which should be allocated and then deleted instead of using a std::vector
I also added a function which uses the iovec. It is called void MyClass::print_data(). It prints all the data in the vector iovecs
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/uio.h>
using namespace std;
class MyClass
{
vector<struct iovec> iovs;
vector<string> bufs;
public:
MyClass();
~MyClass();
void fill_data(const string &data);
void print_data();
};
MyClass::MyClass()
{
cout << "Inside constructor" << endl;
}
MyClass::~MyClass()
{
}
void MyClass::fill_data(const string &data)
{
stringstream stream;
stream << setw(2) << setfill(' ') << (this->bufs.size() + 1) << ". "
<< data << endl;
this->bufs.push_back(stream.str());
iovec iov = {&(bufs.back()[0]), bufs.back().size()};
this->iovs.push_back(iov);
}
void MyClass::print_data() {
writev(STDOUT_FILENO, iovs.data(), iovs.size());
}
int main() {
MyClass my_obj;
string str = "Hey, welcome to my first class!";
for (int i = 0; i < 10; ++i) {
my_obj.fill_data(str);
}
my_obj.print_data();
return 0;
}
compile it like so: g++ test.cpp
Related
I know there is something wrong with the class member functions because I comment everything in them out and the program will run fine but when I uncomment anything it stops working. The constructor runs fine as well.
Here is my CharArray.h file:
#ifndef CHARARRAY_H
#define CHARARRAY_H
class CharArray
{
private:
char * pArray;
int iSize;
public:
CharArray(int size)
{
char *pArray = nullptr;
iSize = size;
pArray = new char[iSize];
pArray = '\0';
}
void setItem (int loc, char ch);
char getItem (int loc);
~CharArray()
{
delete [] pArray;
}
};
#endif // CHARARRAY_H
Here is my member functions:
#include <iostream>
#include <cstring>
#include <iomanip>
#include <cstdio>
#include "CharArray.h"
using namespace std;
void CharArray::setItem (int loc, char ch)
{
pArray[loc] = ch;
cout << pArray[loc] << endl;
return;
}
char CharArray::getItem (int loc)
{
char c;
c = pArray[loc];
return c;
}
And here is my main file:
#include <iostream>
#include <iomanip>
#include "CharArray.h"
using namespace std;
int main()
{
CharArray myChar (5);
int size;
char cstr[10] = "Drew";
myChar.setItem(1, 'A');
char c = myChar.getItem(5);
cout << c << endl;
return 0;
}
Your first problem is in the constructor:
CharArray(int size)
{
char *pArray = nullptr; // <-- unrelated to the pArray in the object!
iSize = size;
pArray = new char[iSize];
pArray = '\0'; // <-- we just lost the handle to new array
}
That last line should instead be:
*pArray = '\0';
Also, it would be better to use a more modern constructor style such as this:
CharArray(int size)
: pArray(new char[size]),
iSize(size)
{
*pArray = '\0';
}
I have a std::vector<short> and would like to compress (and later decompress) with the libzpaq from https://github.com/zpaq/zpaq/ to something like char* buffer.
However I don't get the concept of this Reader and Writer class mentioned in the header file. How do I put my std::vector in to get a compressed buffer out?
Currently I have something like the following code.
#include <vector>
#include <string>
#include <stdio.h>
#include "libzpaq.h"
struct writer: public libzpaq::Writer {
void put(int c) {
}
};
struct reader: public libzpaq::Reader {
int get() {
}
};
void libzpaq::error(const char* msg) {
fprintf(stderr, "Oops: %s\n", msg);
exit(1);
}
int main() {
short a[] = {2,5,8,2,4,2,2,2,6,5,4,3,4,2,2};
std::vector<short> v(a, a+15);
char* buffer;
reader in;
writer out;
libzpaq::compress(&in, &out, "5");
}
And I wan't to compress the vector v into buffer. (And later decompress it again.)
But I don't understand the concept of the Reader and Writer struct/class.
The docu (http://mattmahoney.net/dc/libzpaq.3.html) also mentions the functions virtual int read(char* buf, int n) and virtual void write(const char* buf, int n) for the Reader and Writer. How can I cast a std::vector<short> to char* buf end get the length in n bytes of this buf?
Edit 1: I found a class StringBuffer in libzpaq.h line 1376. But something like
buffer = reinterpret_cast<char*> (&v[0]);
length = sizeof(short)*v.size();
libzpaq::StringBuffer inString, outString;
inString.read(buffer, length);
libzpaq::compress(&inString, &outString, "5");
std::cout << "size outstring: " << outString.size() << std::endl;
std::cout << "size instring: " << inString.size() << std::endl;
always gives me
size outstring: 0
size instring: 0
Even if I try it with a much larger vector v of some thousend random elements.
With Reader you provide byte by byte access to the data you want to compress. So with std::vector<short> it would look like this.
struct reader : public libzpaq::Reader {
reader(const std::vector<short>& v) :
m_v(v),
m_offset(0) {
}
int get() {
if (m_offset < m_v.size() * sizeof (short)) {
return *((char*) m_v.data() + m_offset++);
} else {
return -1;
}
}
int m_offset;
std::vector<short> m_v;
};
Writer should collect output data of the Reader. If you want to collect it in char array I could recommend to do it like this.
struct writer : public libzpaq::Writer {
void put(int c) {
m_buffer.push_back(c);
}
int size() {
m_buffer.size();
}
void copy_to(char* dst) {
memcpy(dst, m_buffer.data(), m_buffer.size());
}
std::vector<char> m_buffer;
};
Then call it:
writer w;
reader r(v1);
libzpaq::compress(&r, &w, "5");
char* buffer = new char[w.size()];
w.copy_to(buffer);
If you want to use StringBuffer then you should write some data to buffer, before read, that why it returns 0. Look at example:
char* buffer = reinterpret_cast<char*> (&v[0]);
int length = sizeof (short)*v.size();
libzpaq::StringBuffer in, out1, out2;
// fill buffer with source data
in.write(buffer, length);
// compress to out1
libzpaq::compress(&in, &out1, "5");
// decompress out1 to out2
libzpaq::decompress(&out1, &out2);
// check result
short* b = (short*)out2.data();
for(int i = 0; i < 15; ++i) {
std::cout << b[i] << std::endl;
}
This question already has answers here:
Need help regarding saving variables via fstream, do I need to use vector?
(2 answers)
Closed 8 years ago.
I got this problem, where I want to make a Devicelist, which I do with a vector of Devices. But I can't make it read/write correctly.
This is my functions:
#include "Devicelist.h"
bool Devicelist::AddDevice(const char *deviceName, char *type)
{
Device tempDevice(deviceName, type, ++id_);
Devicelist_.push_back(tempDevice);
return true;
}
bool Devicelist::deleteDevice(const char *deviceName)
{
for (int i = 0; i < Devicelist_.size(); i++)
{
if (strcmp(deviceName, Devicelist_[i].getName()) == 0)
{
Devicelist_.erase(Devicelist_.begin() + i);
return true;
}
else
{
cout << "No Device found with that Devicename." << endl;
return false;
}
}
}
bool Devicelist::SaveToFile()
{
//remove("Devices.dat");
ofstream SaveFile("Devices.dat", ios::out | ios::binary);
if (!SaveFile)
{
cerr << "File could not be opened." << endl;
return false;
}
for (int i = 0; i < Devicelist_.size(); i++)
SaveFile.write((const char *)(&Devicelist_[i]), sizeof(Devicelist_[i]));
SaveFile.close();
return true;
}
bool Devicelist::LoadFromFile()
{
ifstream LoadFile("Devices.dat", ios::in | ios::binary);
if (!LoadFile)
{
cerr << "File could not be opened." << endl;
return false;
}
for (int i = 0; i < Devicelist_.size(); i++)
LoadFile.read((char *)(&Devicelist_[i]), sizeof(Devicelist_[i]));
LoadFile.close();
return true;
}
Device Devicelist::findDevice(const char *deviceName)
{
for (int i = 0; i < Devicelist_.size(); i++)
{
if (strcmp(deviceName, Devicelist_[i].getName()) == 0)
return Devicelist_[i];
else
cout << "Couldn't find device." << endl;
}
}
And this is my main:
#include "Devicelist.h"
void main()
{
Devicelist list;
list.AddDevice("Lampe3", "Lampe");
list.AddDevice("Lampe4", "Lampe");
list.SaveToFile();
Devicelist list2;
list2.LoadFromFile();
Device lampe = list2.findDevice("Lampe");
cout << lampe.getName() << endl;
cout << lampe.getID() << endl;
cout << lampe.getType() << endl;
}
Can anyone see what my problem is?
Thanks in advance!
Edit1:
My .h-file for Devicelist is:
#ifndef DEVICELIST_H
#define DEVICELIST_H
#include "Device.h"
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
class Devicelist
{
public:
Devicelist();
bool SaveToFile();
bool LoadFromFile();
bool AddDevice(const char *deviceName, char *type);
bool deleteDevice(const char *deviceName);
Device findDevice(const char *devicename);
private:
vector<Device> Devicelist_;
int id_;
};
#endif
This is my Device .h-file:
#ifndef DEVICE_H
#define DEVICE_H
#include <iostream>
#include <string>
#define DNAME_SIZE 33
using namespace std;
class Device
{
public:
Device(const char *devicename = "Default", char *type = "type", int id = 0);
const char *getName();
int getID();
int getType();
private:
char deviceName_[DNAME_SIZE];
int id_;
int type_;
};
#endif
And Device .cpp-file:
#include "Device.h"
Device::Device(const char *deviceName, char *type, int id)
{
strncpy_s(deviceName_, deviceName, DNAME_SIZE);
if (type == "Lampe")
type_ = 1;
else if (type == "Roegalarm")
type_ = 2;
else if (type == "Tyverialarm")
type_ = 3;
else
{
type_ = 0;
cout << "Type does not exists." << endl;
}
id_ = id;
}
const char *Device::getName()
{
return deviceName_;
}
int Device::getID()
{
return id_;
}
int Device::getType()
{
return type_;
}
The problem is when I try to read view what's saved in the file, this is the output:
http://imgur.com/P8WEAKq
The problem is here in the LoadFromFile function, I think:
for (int i = 0; i < Devicelist_.size(); i++)
LoadFile.read((char *)(&Devicelist_[i]), sizeof(Devicelist_[i]));
The DeviceList is empty, or has the wrong size.
You could write something similar as in AddDevice:
Device tempDevice();
LoadFile.read((char *)(&tempDevice), sizeof(tempDevice));
Devicelist_.push_back(tempDevice);
but the size (how many devices) of the file needs to be known.
As mentioned in a comment, this works only if Device doesn't have pointers to other objects for example. It should be a POD (Plain Old Data) object.
An elegant solution would be to implement streaming operators on Device
You will need to to have Device::StoreToFile write the number of devices before writing out each device. This will enable your Device::LoadFromFile to know how many device instances to read from the file.
I highly recommend you do not write a class or structure bit for bit to the file. If your class or struct has any advanced data structures, such as std::string or std::vector, you can't write them in binary. They may use pointers to memory, which will not be the same when you load them.
Here is a better solution:
1. Pass a buffer of uint8_t to the load and store methods.
2. The methods load from the buffer or store into the buffer (append).
3. The caller reads or writes the buffer to file.
4. The class also has a "size on file" method that returns the space occupied on a file, which may be different than the structure size.
Also search the web for "boost::serialization".
I'm trying to dust off my C++. I knocked together a simple program to find the Fibonacci sequence with memoization. There's a memory leak, and I can't seem to figure out why. The leak is reported in Fibonacci::setToFind.
Sorry for the long code chunk, but I couldn't figure out how to make a more minimal reproducible example.
#include <iostream>
class Fibonacci
{
public:
int m_valuefound;
int m_tofind;
long int *m_memo;
int findValue(int value){
if (m_memo[value] == 0) {
if (value == 0 || value == 1) {
m_memo[value] = 1;
} else {
m_memo[value] = findValue(value-1) + findValue(value-2);
}
}
return m_memo[value];
}
void setToFind(int value){
m_tofind = value;
m_memo = new long int[value];
std::fill_n(m_memo,value,0);
}
void solve(){
int value = m_tofind;
int result = findValue(value);
std::cout<< "Value is: " << result << std::endl;
}
~Fibonacci(){};
};
int main (int argc, char * const argv[]) {
std::cout << "Enter integer values until you'd like to quit. Enter 0 to quit:";
int user_ind=0;
// for testing non-interactivly
while(true){
for (user_ind=1; user_ind<45; user_ind++) {
Fibonacci *test = new Fibonacci;
test->setToFind(user_ind);
test->solve();
delete test;
}
}
return 0;
}
You never delete m_memo in the destructor of Fibonacci.
Since you're allocating m_memo as an array, you should delete with delete[] m_memo
Here is working code with a non-copyable Fibonacci class. Why don't
you allocate the memory in the constructor. Use RAII wherever possible
and remember The Rule of Five. Avoid all of this in the first place by
using std::vector.
#include <iostream>
class Fibonacci
{
public:
int m_valuefound;
int m_tofind;
long int *m_memo;
int findValue(int value){
if (m_memo[value] == 0) {
if (value == 0 || value == 1) {
m_memo[value] = 1;
} else {
m_memo[value] = findValue(value-1) + findValue(value-2);
}
}
return m_memo[value];
}
void setToFind(int value){
m_tofind = value;
m_memo = new long int[value];
std::fill_n(m_memo,value,0);
}
void solve(){
int value = m_tofind;
int result = findValue(value);
std::cout<< "Value is: " << result << std::endl;
}
// why don't you allocate in the constructor?
Fibonacci() : m_valuefound(0), m_tofind(0), m_memo(nullptr) {}
~Fibonacci() {
delete[] m_memo;
};
// make the class non-copyable
Fibonacci(const Fibonacci&) = delete;
const Fibonacci& operator=(const Fibonacci&) = delete;
/*
C++03 non-copyable emulation
private:
Fibonacci(const Fibonacci&);
const Fibonacci& operator=(const Fibonacci&);
*/
};
You are allocating m_memo in setToFind:
m_memo = new long int[value];
but your destructor does not have a delete [] m_memo. You should initialize m_memo in your constructor and make you class non-copyable by disabling your copy constructor and assignment operator using delete if using C++11:
Fibonacci(const Fibonacci&) = delete;
const Fibonacci& operator=(const Fibonacci&) = delete;
Otherwise you can make them private. If you used a container such as std::vector your life would be much simpler.
I suggest you use more the STL algorithms. Here's a code snippet with a rather not optimized functor but you can get the idea of the power of the STL:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
class Fibonacci
{
public:
Fibonacci();
~Fibonacci() {}
int operator()();
private:
int n0_;
int n1_;
int n_;
};
Fibonacci::Fibonacci():n0_(0),n1_(1),n_(0)
{
}
int Fibonacci::operator()()
{
if(n_ > 1)
return (++n0_) + (++n1_);
else
return ++n_;
}
using namespace std;
int main()
{
Fibonacci func;
vector<int> v;
//generate 100 elements
generate_n(v.begin(),100,func);
//printing the values using a lambda expression
for_each(v.begin(),v.end(),[](const int val){cout << val << endl;});
return 0;
}
You can then apply the finding algorithm you want on the vector using find_if and defining your own functor.
I have one application in which following task are to be done
1.) UI application will send command code (integer value).
2.) DLL interface(in c++) will get that integer value and execute corresponding command function.
commands name and command code are maintained as
#define PING 50
there will be 500 commands and applying SWITCH CASE will not sound good. so i decided to implement function pointer in my code as below
#include "stdafx.h"
#include<iostream>
#define PING 20
using namespace std;
//extern const int PING = 10;
void ping()
{
cout<<"ping command executed";
}
void get_status(void)
{
cout<<"Get_status called"<<endl;
}
class ToDoCommands
{
public:
void getCommand( void (*CommandToCall)() );
};
void ToDoCommands::getCommand( void (*CommandToCall)())
{
void (*CommandToCall1)();
CommandToCall1 = CommandToCall;
CommandToCall1();
}
int main()
{
int code;
ToDoCommands obj;
cout<<"enter command code";
cin>>code; // if UI send 50 then Ping function get executed as #define PING 50
obj.getCommand(ping); // here m passing ping manually..
//obj.getCommand(get_status);
return 0;
}
how can i pass command name corresponding to command code in
obj.getCommand(ping);
You are almost there: make a std::map of std::string to function pointer, initialize it with data pairing a string name to a corresponding function pointer, and then use that map at runtime to pick the correct pointer based on the string parameter passed in.
#include <iostream>
#include <string>
#include <map>
using namespace std;
void ping() {
cout << "ping" << endl;
}
void test() {
cout << "test" << endl;
}
int main() {
map<string,void(*)()> m;
m["ping"] = ping;
m["test"] = test;
// I am using hard-coded constants below.
// In your case, strings will come from command line args
m["test"]();
m["ping"]();
return 0;
}
Link to a demo with std::map.
Here is how you can do it without a map (it will be slower because of the linear search, but you can fix it by ordering names alphabetically and using binary search).
#include <iostream>
#include <cstring>
using namespace std;
void ping() {
cout << "ping" << endl;
}
void test() {
cout << "test" << endl;
}
typedef void (*fptr_t)();
int main() {
const fptr_t fptrs[] = {test, ping};
const char *names[] = {"test", "ping"};
const char *fname = "test";
for (int i = 0 ; i != 2 ; i++) {
if (!strcmp(fname, names[i])) {
fptrs[i]();
break;
}
}
return 0;
}
Link to a demo with arrays.
Declare an array of function pointers. Where you treat the index as your "code". For example:
void foo(){
printf("foo\n");
}
void bar(){
printf("bar\n");
}
int main(void)
{
void (*code_to_function[100])();
int code;
code_to_function[0] = foo;
code_to_function[1] = bar;
printf("Enter code: ");
scanf("%d", &code);
code_to_function[code]();
return 0;
}
Please note that for this rudimentary example, inputting integer code other than 0 and 1 will result in a segfault.
I should say #dasblinkenlight is right but if you don't want to use std::map you should implement a map yourself. This can be buggy and not a optimized way, but if you don't want to use STL, it seems you should implement it yourself.
You can use 2 arrays with corresponding indices. One of them is a char * array and another one is function pointers. They are better to be encapsulated in a class named something like MyMap.
class MyMap {
public:
...
inline void add(char *name, (void (*ptr)(void)) ) {
names_[currIndex_] = name; // Or stcpy
ptrs_[currIndex_] = ptr;
currIndex_++;
}
inline (void(*)(void)) get(char *name) {
int foundIndex = -1;
for (int i = 0; i < currIndex_; i++) {
// Find matching index
}
if (foundIndex_ >= 0) {
return ptrs_[foundIndex_];
}
return NULL;
}
private:
int currIndex_;
char *names_[10];
(void (*ptrs_[10])(void));
};