I have a class in C++ that represents a buffer where I can store unsigned char. I have two methods, one the add generic values using templates and another to retrieve the values. When I am trying to retrieve the values I am getting Segmentation fault (core dumped). I am using memcpy If I change to use std::copy(value, value, _valueChar); I get other errors: error: no type named ‘value_type’ in ‘struct std::iterator_traits<int>’
#include <iostream>
#include <cstring>
#include <utility>
#include <vector>
#include <string>
class SkinnyBuffer {
private:
unsigned char *_valueChar;
std::size_t _sizeChar;
public:
SkinnyBuffer();
SkinnyBuffer(std::size_t size);
~SkinnyBuffer();
void clean();
template<typename T>
void addValue(T value) {
if (_valueChar != nullptr) {
delete[] _valueChar;
}
// _sizeChar = n; // assume _size is a field
// _valueChar = new unsigned char[_sizeChar];
// std::copy(value, value, _valueChar);
memcpy(_valueChar, &value, sizeof(value));
}
template<typename T>
void addValue(std::size_t offset, T value) {
if (_valueChar != nullptr) {
delete[] _valueChar;
}
// _sizeChar = n; // assume _size is a field
// _valueChar = new unsigned char[_sizeChar];
// std::copy(value, value + offset, _valueChar);
memcpy(_valueChar + offset, &value, sizeof(value));
}
unsigned char *getValue() {
return _valueChar;
}
};
#include "SkinnyBuffer.h"
SkinnyBuffer::SkinnyBuffer() {
}
SkinnyBuffer::SkinnyBuffer(std::size_t size) {
_sizeChar = size;
_valueChar = new unsigned char[_sizeChar];
}
SkinnyBuffer::~SkinnyBuffer() {
}
void SkinnyBuffer::clean() {
_valueChar = new unsigned char[_sizeChar];
}
int main(int argc, char *argv[]) {
int value = 50;
int offset = sizeof(value);
SkinnyBuffer b(offset);
b.addValue(value);
int dValue;
memcpy(&dValue, b.getValue(), offset);
std::cout << dValue << std::endl;
}
In addValue you explicitly delete the _valueChar buffer. Then the next line along you write into the deleted buffer. What did you expect this code to do?
This is the first of many issues in your code regarding memory management.
Just use a std::vector and as long as its big enough you wont have any of those issues.
Related
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
I am importing a mat file to my C++ code. After importing data, performing calculations and saving to another place I want to free the memory occupied by the original data.
Is there any specific function to perform that. Would just deleting the pointer returned by mxGetData() free the memory?
This is the class I have created to import mat file
#ifndef READMAT_H
#define READMAT_H
#include "mat.h"
#include "matrix.h"
#include "mex.h"
#include "program_exception.h"
#include "stdint.h"
class readmat
{
private:
const size_t *dimarray;
const char **dir;
MATFile *pmat;
int ndir;
mxArray *painfo,*pa;
const char *file;
int minute;
int second;
const char *name;
const char *name1;
bool isdouble;
no_mat_exception noMAT;
public:
//with default value
readmat(const char *f);
// get number of dimensions
int getnumbrofdimensions() const;
// get pointer to array
void* getarraypointer() const;
// get pointer to each dimension size
const size_t* dimensionpointer() const;
//number of elements
int numberofelements() const;
~readmat();
};
#endif
The following is the cpp implementation
#include "readmat.h"
#include <iostream>
#include "mat.h"
#include "matrix.h"
#include "mex.h"
using namespace std;
// set the file name
readmat::readmat(const char *f)
{
file = f;
pmat = matOpen(file, "r");
if (pmat == NULL) {
throw noMAT;
}
else
{
dir = (const char **)matGetDir(pmat, &ndir);
if (dir == NULL) {
printf("Error reading directory of file %s\n", file);
}
else if (ndir > 1)
{
cout << "The number of variables are larger than 1" << endl;
}
else
{
mxFree(dir);
matClose(pmat);
pmat = matOpen(file, "r");
if (pmat == NULL) {
throw noMAT;
}
else
{
painfo = matGetNextVariableInfo(pmat, &name);
matClose(pmat);
}
pmat = matOpen(file, "r");
if (pmat == NULL) {
throw noMAT;
}
else
{
pa = matGetNextVariable(pmat, &name1);
matClose(pmat);
}
}
}
}
int readmat::getnumbrofdimensions() const
{
return mxGetNumberOfDimensions(painfo);
}
void* readmat::getarraypointer() const
{
//return mxGetPr(pa);
return mxGetData(pa);
}
const size_t* readmat::dimensionpointer() const
{
return mxGetDimensions(painfo);
}
int readmat::numberofelements() const
{
return mxGetNumberOfElements(painfo);
}
readmat::~readmat()
{
mxFree(pa);
mxFree(painfo);
}
Here when I delete the object program trigger a break point in the file free.c.
The MATLAB demo on edit([matlabroot '/extern/examples/eng_mat/matdgns.c']); seems to suggest using mxDestroyArray instead of mxFree.
When calling mxGetData(). The only thing the function does, is returning a pointer to the real (in contrast to imaginary) data that is stored in the mxArray.
So there is no need to free memory, since nothing is dynamically allocated during this call.
I'm using C++ and am trying to set an array element values with a setter method. The array is a class private member:
class Boo{
private:
int *x;
public:
Boo();
~Boo();
void setX(int,int);
int getX(int);
}
Boo::Boo(){
x = new int[1];
x = 0;
}
void Boo::setX(int value, int index){
//set condition for NULL
x[index] = value;
}
int Boo::getX(int index){
if(x[index] == NULL) {cout<<"invalid index"<<end; return;}
return x[index];
}
void test(){
Boo *p = new Boo();
p->setX(12,0);
cout<<p->getX(0)<<endl;
}
I been trying to test setting the values in 'x' starting with index '0' (like test()) but it crashes. I wanted to write a program where I run a loop counting up, and I set the array values. Can this be accomplish this way?
Do not use new in C++!
In this case, you should use std::vector<int>.
If you want to fix your code unless use std::vector,
#include <cstddef>
#include <iostream>
#include <stdexcept>
#include <memory>
using std::size_t;
class Boo {
private:
int *x;
size_t size;
size_t capacity;
public:
Boo();
~Boo();
void setX(int,size_t);
int getX(size_t);
};
Boo::Boo() : size(), capacity(1) {
this->x = new int[1];
//x = 0;//DO NOT ASSIGN NULL POINTER!!!!
}
Boo::~Boo() noexcept {
delete[] x;
}
void Boo::setX(int value, size_t index){
if(this->capacity <= index) throw std::out_of_range("Boo::setX");//YOU MUST CHECK RANGE
this->x[index] = value;
++this->size;
}
int Boo::getX(size_t index){
if(this->size <= index) throw std::out_of_range("Boo::getX");//YOU MUST CHECK RANGE
return x[index];
}
void test(){
auto p = std::make_unique<Boo>();
p->setX(12,0);
std::cout << p->getX(0) << std::endl;
}
int main(){
test();
}
http://melpon.org/wandbox/permlink/aIhwC5c9o1q8ygIo
Boo::Boo()
{
x = new int[1];
x = 0;
}
you are not able to set value in an array because after initializing with memory, you have set the pointer of an array to null in constructor.
please use x[0] = 0; instead of x = 0;
#include <iostream>
using namespace std;
template <class T>
T sortArray(T data[])
{
int arrsize = sizeof(data)/sizeof(T);
int x,y,temp;
for(y=0;y<arrsize;y++)
{
for(x =0;x<arrsize-y-1;x++)
{
if(data[x]>data[x+1])
{
temp = data[x];
data[x] = data[x+1];
data[x+1] = temp;
}
}
}
return data;
}
int main()
{
int x;
int arr[] = {10,7,32,65,12,6};
int sorted[] = sortArray(arr[]);
for(x=0;x<6;x++)
{
cout<<sorted[x]<<endl;
}
}
When i try to sort compile this code i get an error of
**abc\main.cpp:34: error: expected primary-expression before ']' token
int sorted[] = sortArray(arr[]);
^**
How to fix this bug . if i remove [] i get more errors
Quite a lot wrong. Fixed it here:
#include <iostream>
using namespace std;
template <class T>
T* sortArray(T data[], int arrsize) // better pass the size of the array, and return T*
{
int x,y,temp;
for(y=0;y<arrsize;y++)
{
for(x =0;x<arrsize-y-1;x++)
{
if(data[x]>data[x+1])
{
temp = data[x];
data[x] = data[x+1];
data[x+1] = temp;
}
}
}
return data;
}
int main()
{
int x;
int arr[6] = {10,7,32,65,12,6};
int *sorted = sortArray(arr, sizeof(arr)/sizeof(arr[0])); // pass size of array
for(x=0;x<6;x++)
{
cout<<sorted[x]<<endl;
}
}
Output:
6
7
10
12
32
65
T sortArray(T data[])
is supposed to return a T, but you are useing an int array to catch it:
int sorted[] = sortArray(arr[]);
To work out, you can change this method to (you don't need to return it, i.e. removing the return line):
void sortArray(T data[])
and call it like:
sortArray<int>(arr);
The return type of sortArray is T but what you return is data of type T[]. You should change to the following prototype:
T* sortArray(T data[]);
You are doing bubble sort.
You need to fix the method signature as follows:
T * sortArray(T * data)
{
In the main(), you need to fix the calls:
int * sorted = sortArray(arr);
This should fix the errors. Basically, you are sending in a pointer to an array, and you want the method to return a pointer to a sorted array.
When I try debugging the code, it runs into the debugging error "c++ Expression: string subscript out of range"
Pretty sure the problem was brought while calling setCode().
How do I fix the code inside setCode()?
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <list>
using namespace std;
class test
{
private:
string code;
int digit;
public:
//constructor
test(): code(""), digit(0) { }
//copy constructor
test(const test &other):
digit(other.digit)
{
for(unsigned int i=0; i < code.length(); i++)
code[digit] = other.code[digit];
}
//set up the private values
void setCode(const string &temp, const int num);
void setDigit(const int &num);
//return the value of the pointer character
const string &getCode() const;
const unsigned int getDigit() const;
};
const string& test::getCode() const
{
return code;
}
const unsigned int test::getDigit() const
{
return digit;
}
void test::setCode(const string &temp, int num)
{
code[num] = temp[num];
}
void test::setDigit(const int &num)
{
digit = num;
}
int main()
{
string contents = "dfskr-123";
test aisbn;
list<test> simul;
list<test>::iterator testitr;
testitr = simul.begin();
int count = 0;
cout << contents << '\n';
aisbn.setCode(contents, count);
aisbn.setDigit(count);
simul.push_back(aisbn);
count++;
/*for(; testitr !=simul.end(); simul++)
{
cout << testitr->getCode() << "\n";
}*/
}
When you create an instance of the test class, the string inside it is empty. This means that whenever you do e.g. code[something] you will be out of range. It doesn't matter what the index is.
You either need to set the string to a certain length from the start, and make sure that the index is within the range. Or to make sure that the index is within range by dynamically extending the string when needed.
You have to make sure that when this statement executes:
code[num] = temp[num];
both code and temp are at least of size num + 1.