Char* data changes when accessed - c++

I am working on a c++ application that has a function
//ControllerCore.cpp
Report ControllerCore::GetReport() {
unsigned char buf[256];
int res = 0;
while (res == 0) {
res = get_unsigned_char*(buf, sizeof(buf));
if (res < 0)
printf("Unable to read()\n");
#ifdef WIN32
Sleep(50);
#else
usleep(50 * 1000);
#endif
}
Report report = Report();
report.data = buf;
report.dataLength = res;
return report;
}
Report is defined as
//Report.h
struct Report
{
public:
unsigned char* data;
int dataLength;
};
When ContollerCore::GetReport() returns it assigns report.data to the pointer to an array of unsigned characters that I can work with fine. But when the caller tries to print report.data the values of the array change.
//Main.cpp
int RequestReport() {
Report report = core.GetReport();
for (int i = 0; i < report.dataLength; i++) {
std::cout << "0x" << std::hex << (int)report.data[i] << ", ";
}
std::cout << std::endl;
return 1;
}

You're returning a pointer to a local array. As soon as ControlerCore::GetReport returns, buf goes out of scope and is destroyed. Any attempt to access it after that leads to undefined behavior.
You need make Report actually hold the data directly. The easiest way would be to use a std::vector:
struct Report
{
std::vector<unsigned char> data;
// don't need dataLength anymore since std::vector knows its size
};
Report ControllerCore::GetReport() {
Report report;
report.data.resize(256);
int res = 0;
while (res == 0) {
res = get_data(report.data.data(), report.data.size());
}
report.data.resize(res);
return report;
}
Now that Report has only one member it probably isn't needed anymore, and you could just return std::vector<unsigned char> directly instead.
If you want to avoid the dynamic allocation used by std::vector, you could use std::array (or a raw array) instead:
struct Report
{
std::array<unsigned char, 256> data;
size_t dataLength; // back now, since the length of the data won't match the size of the contianer
};
Report ControllerCore::GetReport() {
Report report;
int res = 0;
while (res == 0) {
res = get_data(report.data.data(), report.data.size());
}
report.dataLength = res;
return report;
}
This avoids the dynamic allocation, but does incur an extra copy of the data since std::array can't be efficiently moved like std::vector can. That means that unless dynamic allocation is especially slow on your platform, the std::vector version is probably going to be faster.

You can try using report.data itself instead of buf.
Report ControllerCore::GetReport() {
Report report;
report.data=new char[256];
int res = 0;
while (res == 0) {
res = get_unsigned_char*(report.data, sizeof(char)*256);
if (res < 0)
printf("Unable to read()\n");
#ifdef WIN32
Sleep(50);
#else
usleep(50 * 1000);
#endif
}
report.dataLength = res;
return report;
}

Related

C++ Parsing and Storing any kind of data

I'm working on a text-based a simple command processor for a microcontroller project (C and C++). It implements an "explicit setter" so to speak. It means that I store pointers to target memory locations and set them to the incoming data.
First of cource, I parse the data based a predefined set of syntactical rules:
"12345" -> string (char*)
12345 -> unsigned int
12.45 -> float
-123456 -> int (signed)
This is the method I've come up with:
void* CommandInterpreter::ParseArgumentValue(std::string token, size_t* ptrSize = nullptr) {
try {
void* value = NULL;
if(std::count(token.begin(), token.end(), '.') == 1) {
auto result = (float)std::atof(token.c_str());
value = malloc(sizeof(float));
ptrSize = sizeof(float);
memcpy(value, &result, sizeof(float));
} else if(token.front() == '"' && token.back() == '"') {
const char* result = token.substr(1, token.size()-2).c_str();
size_t size = (strlen(result) * sizeof(uint8_t)) + 1;
value = malloc(size);
ptrSize = size;
memcpy(value, result, size);
} else if(token.front() == '-') {
auto result = (int)std::atoi(token.c_str());
value = malloc(sizeof(int));
ptrSize = sizeof(int);
memcpy(value, &result, sizeof(int));
} else {
auto result = (unsigned int)std::stoul(token.c_str());
value = malloc(sizeof(unsigned int));
ptrSize = sizeof(unsigned int);
memcpy(value, &result, sizeof(unsigned int));
}
return value;
} catch(std::invalid_argument) {
//return NULL;
} catch(std::out_of_range) {
//return NULL;
}
}
I know it's not pretty, and it borders on bad-practice but it works.. however this will need to be freed after I process the value.
The actual setter-part looks like this:
auto setterdef = this->mDefinitions2[tokens[1]];
void* value = ParseArgumentValue(tokens[2]);
memcpy(setterdef.TargetPtr, value, setterdef.TargetSize);
if(memcmp(setterdef.TargetPtr, value, setterdef.TargetSize) != 0)
throw "COULD_NOT_SET";
free(value);
rbuilder.SetName("OK");
return rbuilder.Get();
The setter part works well, however I want to use the same function to parse an incoming parameter list and then store it in an std::map<std::string, void*> but this will keep the allocated memory even after the map is destroyed; as of right now I have a foreach in the destructor of my CommandParameterList class which frees the pointers in the map.. but it seems pretty odd to me.
My question would be.. how bad is this? And is there a better way to do this?
I know about std::any however, as far as I know I cannot just memcpy X amount of bytes from it, and I'd need to know the specific type to std::any_cast it.

Debug Assertion Failed error when accessing function in DLL

I'm currently learning how to create a C++ library to be referenced in other projects, and I am running into an issue with a "Debug Assertion Failed" error: is_block_type_valid(header-> _block_use). I followed the walkthrough shown here: Create and use your own Dynamic Link Library. Oddly, I am getting the expected answer if I just ignore the error.
My DLL currently only has one function:
cpp:
int calculate_crc(std::string msg)
{
std::vector<std::string> msg_vector = [](std::string& msg1) {
std::string next;
std::vector<std::string> result;
// for each char in string
for (std::string::const_iterator it = msg1.begin(); it != msg1.end(); it++)
{
// if we hit a terminal char
if (*it == ' ')
{
if (!next.empty())
{
// add them to the result vector
result.push_back(next);
next.clear();
}
}
else
{
next += *it;
}
}
if (!next.empty())
{
result.push_back(next);
}
return result;
} (msg);
int crcReg = 0xFFFF;
// iterate through each element in msgVector
for (auto&& element : msg_vector)
{
// step 2: xor operation performed on byte of msg and CRC register
crcReg ^= [](std::string hex) {
std::map<char, int> map;
map['0'] = 0;
map['1'] = 1;
map['2'] = 2;
map['3'] = 3;
map['4'] = 4;
map['5'] = 5;
map['6'] = 6;
map['7'] = 7;
map['8'] = 8;
map['9'] = 9;
map['a'] = 10;
map['b'] = 11;
map['c'] = 12;
map['d'] = 13;
map['e'] = 14;
map['f'] = 15;
return map[hex[1]] + (map[hex[0]] * 16);
} (element);
// step 3-5 are repeated until 8 bit shifts
for (int i = 0; i < 8; i++)
{
int crcCopy = crcReg;
crcReg >>= 1;
if ((crcCopy & 1) == 0)
continue;
else
crcReg ^= 0xA001;
}
}
return crcReg;
}
h:
#pragma once
#ifdef OMRONLIBRARY_EXPORTS
#define OMRONLIBRARY_API __declspec(dllexport)
#else
#define OMRONLIBRARY_API __declspec(dllimport)
#endif
#include <iostream>
extern "C" OMRONLIBRARY_API int calculate_crc(const std::string msg);
std::string is not a safe type to use in a DLL function parameter. Non-POD types should never be passed over a DLL boundary, unless they are type-erased (such as by using a void* pointer) and are only ever accessed directly by code on one side of the boundary and not the other side.
Assuming the caller is even using C++ at all (C-style DLLs can be used in non-C/C++ languages), it may be using a different std::string implementation. Or it may be using a different C++ compiler, or a different version of the same C++ compiler, or even just different settings for alignment, optimizations, etc. And even if all of that matches the DLL, it will likely be using a different instance of the memory manager that the DLL uses for its std::string implementation.
If you want to pass a string to a DLL function safely, use a C-style char* string instead. You can use std::string inside the DLL, if you want to, eg:
int calculate_crc(const char* msg)
{
use msg as-is ...
or
std::string s_msg = msg;
use s_msg as needed ...
}
extern "C" OMRONLIBRARY_API int calculate_crc(const char* msg);

c++ incorrect checksum for freed object-

I am getting this error (memory location varies between runs):
Freeing memory!
Image_Processing(6282,0x100091000) malloc: * error for object 0x1212121212121212: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
in this point it crashes : //delete m_data;
class Uint8Image {
public:
uint32_t m_w;
uint32_t m_h;
uint8_t *m_data;
Uint8Image(uint32_t w, uint32_t h): m_w(w), m_h(h), m_data(0)
{
m_data = new uint8_t(w*h);
}
Uint8Image(const Uint8Image &obj) ;
Uint8Image& operator = (const Uint8Image &D ) {
if(this != &D)
{
delete [] m_data;
m_w= D.m_w;
m_h = D.m_h;
m_data=new uint8_t(m_w * m_h); // deep copy the pointer data
}
return *this;
}
~Uint8Image()
{
std::cout << "Freeing memory!"<< std::endl;
delete m_data; // it crashes here
m_data = NULL;
}
};
class MeniscusFinderContext {
public:
MeniscusFinderContext( uint32_t m_a, uint32_t m_b):
{
m_input_image = new Uint8Image(m_a,m_b);
}
~MeniscusFinderContext()
{
delete m_input_image;
m_input_image = NULL;
}
Uint8Image m_input_image;};
//The function that calls:
// Taking input through option-parsing,
int main(int argc, char *argv[]{
const char *file_name = options[INPUT].arg;
std::ifstream file_stream(file_name,
std::ifstream::in | std::ifstream::binary);
char buf[256];
char *sEnd;
file_stream.getline(buf, sizeof(buf));
if(buf[0] != 'P' || buf[1] != '5') {
std::cerr << "invalid input PGM file" << std::endl;
return 1;
}
file_stream.getline(buf, sizeof(buf));
while(buf[0] == '#') file_stream.getline(buf, sizeof(buf));
uint32_t m_a = strtol(buf, &sEnd, 10);
uint32_t m_b = strtol(sEnd, &sEnd, 10);
MeniscusFinderContext M(m_a,m_b);
file_stream.getline(buf, sizeof(buf));
while(buf[0] == '#') file_stream.getline(buf, sizeof(buf));
if(atoi(buf) != 255) return 3;
file_stream.read((char *)M.m_input_image->m_data ,m_a * m_b);
if(!file_stream) {
std::cerr << "only got " << file_stream.gcount() << std::endl;
return 2;
}
file_stream.close();
return 0;
}
Edit: I'm running it and sometimes it runs while others it gives me the error. Seems to be at a random order. Any hints would be really helpful.
I already have checked all the related answers in stack overflow, but could nt figure it out.
new uint8_t(w*h);
This allocates exactly one uint8_t, whose initial value is w*h.
You probably intended:
new uint8_t[w*h];
Otherwise, this:
file_stream.read((char *)M.m_input_image->m_data ,m_a * m_b);
will immediately overrun this buffer. The same bug occurs several times in the shown code.
delete m_data;
Stuff allocated with new[] should be deallocated with delete[].
In general, your overall approach is very error-prone. Instead of manually handling memory, in this fashion, you should be using std::vector, and iterators. Correct usage of C++'s containers greatly reduces the possibility of making these kinds of bugs.

How do I store a vector of float vectors in shared memory in C++?

I am need to store a vector of float vectors in shared memory in C++. I have a toy example that works, for storing an integer in shared memory. This is the code:
int main()
{
int pid;
int start = 0;
int shmid;
key_t key;
key = 123;
int *shm;
if ((shmid = shmget(key, sizeof(int), IPC_CREAT | 0666)) < 0)
{
perror("shmget");
exit(1);
}
shm = (int *) shmat(shmid, NULL, 0);
pid = fork();
if (pid > 0)
{
wait(NULL);
cout << *shm << *(shm+1);
}
else if (pid == 0)
{
*shm = 6;
*(shm+1) = 7;
}
else
{
exit(-1);
}
cout << endl;
return 0;
}
However, it is my understanding that this is much harder with the datatype vector> instead of a simple integer. Do I need to write a custom allocator (and if so, are there any simple ways to do this? The examples I have found have all been pretty complicated...) to make this work, or is there a simple extension of this example that will let me place a vector> in shared memory?
It is not possible to store a std::vector<T> in a shared memory region, because the actual elements inside the vector aren't stored within the memory of std::vector<T>, but are allocated on the heap.
Technically, you could construct your own allocator, but I would think that it's easier to simply serialize the content of your vector.
Something like this:
vector<float> vec_f;
// some code fills vec_f ..
float *shm;
shm = (float *) shmat(shmid, NULL, 0);
for(auto f : vec_f)
{
*shm++ = f;
}
(Or, if you don't want to use C++ style iteration)
for(size_t i = 0; i < vec_f.size(); i++)
{
*shm++ = vec_f[i];
}

C++ Returning results from several threads into an array

I've a pattern-matching program which takes as input a string and returns a string closely matched by a dictionary. Since the algorithm takes several seconds to run one match query, I am attempting to use multi-threading to run batch queries.
I first read in a file containing a list of queries and for each query dispatch a new thread to perform the matching algorithm, returning the results into an array using pthread_join.
However, I'm getting some inconsistent results. For example, if my query file contains the terms "red, green, blue", I may receive "red, green, green" as the result. Another run may generate the correct "red, green, blue" result. It appears to sometimes be writing over the result in the array, but why would this happen since the array value is set according to the thread id?
Dictionary dict; // global, which performs the matching algorithm
void *match_worker(void *arg) {
char* temp = (char *)arg;
string strTemp(temp);
string result = dict.match(strTemp);
return (void *)(result.c_str());
}
void run(const string& queryFilename) {
// read in query file
vector<string> queries;
ifstream inquery(queryFilename.c_str());
string line;
while (getline(inquery, line)) {
queries.push_back(line);
}
inquery.close();
pthread_t threads[queries.size()];
void *results[queries.size()];
int rc;
size_t i;
for (i = 0; i < queries.size(); i++) {
rc = pthread_create(&threads[i], NULL, match_worker, (void *)(queries[i].c_str()));
if (rc) {
cout << "Failed pthread_create" << endl;
exit(1);
}
}
for (i = 0; i < queries.size(); i++) {
rc = pthread_join(threads[i], &results[i]);
if (rc) {
cout << "Failed pthread_join" << endl;
exit(1);
}
}
for (i = 0; i < queries.size(); i++) {
cout << (char *)results[i] << endl;
}
}
int main(int argc, char* argv[]) {
string queryFilename = arg[1];
dict.init();
run(queryFilename);
return 0;
}
Edit: As suggested by Zac, I modified the thread to explicitly put the result on the heap:
void *match_worker(void *arg) {
char* temp = (char *)arg;
string strTemp(temp);
int numResults = 1;
cout << "perform match for " << strTemp << endl;
string result = dict.match(strTemp, numResults);
string* tmpResult = new string(result);
return (void *)((*tmpResult).c_str());
}
Although, in this case, where would I put the delete calls? If I try putting the following at the end of the run() function it gives an invalid pointer error.
for (i = 0; i < queries.size(); i++) {
delete (char*)results[i];
}
Without debugging it, my guess is that it has something to do with the following:
void *match_worker(void *arg)
{
char* temp = (char *)arg;
string strTemp(temp);
string result = dict.match(strTemp); // create an automatic
return (void *)(result.c_str()); // return the automatic ... but it gets destructed right after this!
}
So when the next thread runs, it writes over the same memory location you are pointing to (by chance), and you are inserting the same value twice (not writing over it).
You should put the result on the heap to ensure it does not get destroyed between the time your thread exits and you store it in your main thread.
With your edit, you are trying to mix things up a bit too much. I've fixed it below:
void *match_worker(void *arg)
{
char* temp = (char *)arg;
string strTemp(temp);
int numResults = 1;
cout << "perform match for " << strTemp << endl;
string result = dict.match(strTemp, numResults);
string* tmpResult = new string(result);
return (void *)(tmpResult); // just return the pointer to the std::string object
}
Declare results as
// this shouldn't compile
//void* results[queries.size()];
std::string** results = new std::string[queries.size()];
for (int i = 0; i < queries.size(); ++i)
{
results[i] = NULL; // initialize pointers in the array
}
When you clean up the memory:
for (i = 0; i < queries.size(); i++)
{
delete results[i];
}
delete [] results; // delete the results array
That said, you would have a much easier time if you used the C++11 threading templates instead of mixing the C pthread library and C++.
The problem is caused by the lifetime of the local variable result and the data returned by the member function result.c_str(). You make this task unnecessary difficult by mixing C with C++. Consider using C++11 and its threading library. It makes the task much easier:
std::string match_worker(const std::string& query);
void run(const std::vector<std::string>& queries)
{
std::vector<std::future<std::string>> results;
results.reserve(queries.size());
for (auto& query : queries)
results.emplace_back(
std::async(std::launch::async, match_worker, query));
for (auto& result : results)
std::cout << result.get() << '\n';
}