C++ What's wrong with these functions? - c++

This is a class I'm doing to organize every memory block I allocate using malloc/calloc, so I can easily dispose of them later. The following is the definition of this class:
#include "memmanager.h"
std::vector<void*> MemoryManager::GarbageCollector(0);
void MemoryManager::AddToGC(void* myThing)
{
if(__DEBUG__MODE__)
MainDebugger.Log("Adding 1 element to GC: %p", "Info", myThing);
MemoryManager::GarbageCollector.push_back(myThing);
return;
}
void MemoryManager::MultiAddToGC(int args, void* myThing, ...)
{
if(args < 1)
return;
#ifdef _DEBUG
MainDebugger.Log("Adding %i element to GC", "Info", args);
#endif
va_list chrstr;
va_start(chrstr, args);
for(int x = 0; x < args; x++)
MemoryManager::GarbageCollector.push_back(va_arg(chrstr, void*));
va_end(chrstr);
return;
}
void MemoryManager::Flush()
{
int lasterror = 0;
#ifdef _DEBUG
MainDebugger.Log("Call to MemoryManager::Flush() with %i items in the GC", "Info", MemoryManager::GarbageCollector.size());
#endif
for(unsigned int x = 0; x < MemoryManager::GarbageCollector.size(); x++)
{
errno = lasterror = 0;
free(GarbageCollector[x]);
lasterror = errno;
if(lasterror > 0)
MainDebugger.Log("MemoryManager::Flush() Error: %s (%i : %p)", "Error", strerror(lasterror), x, GarbageCollector[x]);
}
GarbageCollector.clear();
return;
}
The problem seems to be with the function "MultiAddToGC". When I do this in my main file:
MemoryManager::MultiAddToGC(3,tst,mfile,testfile);
MemoryManager::Flush();
It works fine if I'm in Debug mode (I'm doing this in VC++ 2010). But if I change to Release mode, it gives me an error inside MemoryManager::Flush() while calling the free() function (something about the stack being corrupted). I can continue, if I continue, I get the following in my log:
15:12:26 f 00 (0 fps) | Error > MemoryManager::Flush() Error: Invalid
argument (2 : 00D44784)
However, if I do this:
MemoryManager::AddToGC(tst);
MemoryManager::AddToGC(mfile);
MemoryManager::AddToGC(testfile);
MemoryManager::Flush();
It works both in Debug, and release. No errors. So I'm assuming the error is in MultiAddToGC(), but I can't find it. The following code is the header, "memmanager.h":
#ifndef __MEMMANAGER_H__
#define __MEMMANAGER_H__
#include <vector>
#include <malloc.h>
#include <stdarg.h>
#include "..\core.h"
#include "..\DEBUGGER\debugger.h"
extern bool __DEBUG__MODE__;
extern GameDebugger MainDebugger;
class MemoryManager {
public:
static void MemoryManager::AddToGC(void*);
static void MemoryManager::MultiAddToGC(int, void*,...);
static void MemoryManager::Flush();
private:
static std::vector<void*> GarbageCollector;
protected:
};
#endif
Any help/tips/advise is wellcome.

In va_start(chrstr, args);, the second parameter should be the last named parameter, so myThing (but you probably want to remove myThing in fact).
but I would write
template <typename...Ts>
void MemoryManager::MultiAddToGC(Ts*... myThings)
{
if(sizeof...(myThings) < 1)
return;
#ifdef _DEBUG
MainDebugger.Log("Adding %i elements to GC", "Info", sizeof...(myThings));
#endif
int dummy[] = {(MemoryManager::GarbageCollector.push_back(myThings), 0)...};
(void) dummy; // avoid warning for unused variable
}
or simply
void MemoryManager::MultiAddToGC(const std::initializer_list<void*>& myThings)
{
if(myThings.size() < 1)
return;
#ifdef _DEBUG
MainDebugger.Log("Adding %i elements to GC", "Info", myThings.size());
#endif
MemoryManager::GarbageCollector.insert(MemoryManager::GarbageCollector.begin(),
myThings.begin(), myThings.end());
}

Related

Using Dll to assign a function to the Pointer-Member-Function of a structure passed to it

I have two projects in my Solution (Visual Studio)
I want to assign the function
void _OnCycle()
{
printf("Success\n");
}
in the Dll( main.cpp ) to the pointer member function OnCycle of the structure PluginCallbacks.
extern "C" unsigned int PluginInit(PluginFuncs * pluginFuncs, PluginCallbacks * pluginCalls, PluginInfo * pluginInfo) {
pluginCalls->OnCycle = _OnCycle;
return 1;
}
But program is crashing. Entire code below.
//Project: ConsoleApplication1
//file: Dll1/ConsoleApplication1/ConsoleApplication1.cpp
#include <iostream>
#include "plugin.h"
#include <windows.h>
typedef unsigned int (__stdcall *PluginInit)(PluginFuncs* pluginFuncs, PluginCallbacks* pluginCalls, PluginInfo* pluginInfo);
int main()
{
std::cout << "Loading first dll\n";
HINSTANCE hGetProcIDDLL = LoadLibrary("../Release/Dll1.dll");
if (!hGetProcIDDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
// resolve function address here
PluginInit funci = (PluginInit)GetProcAddress(hGetProcIDDLL, "PluginInit");
if (!funci) {
std::cout << "could not locate the function" << std::endl;
return EXIT_FAILURE;
}
PluginFuncs a;
PluginCallbacks b;
PluginInfo c;
std::cout << "PluginInit(a,b,c) returned " << funci(&a,&b, &c) << "\n";
std::cout << "Now going to call OnCycle\n";
b.OnCycle();
std::cout << "Done";
return EXIT_SUCCESS;
}
//Project: ConsoleApplication1
//file: Dll1/ConsoleApplication1/plugin.h
#pragma once
#include <stdint.h>
## Heading ##
typedef struct _Settings {
uint32_t structSize;
uint32_t flags;
} Settings;
typedef struct _PluginInfo {
uint32_t structSize;
char name[32];
} PluginInfo;
typedef struct _PluginFuncs {
uint32_t structSize;
uint32_t(*GetVersion) (void);
}PluginFuncs;
typedef struct {
uint32_t structSize;
void (*OnCycle) ();
}PluginCallbacks;
and second project
//Project: Dll1
//file: Dll1/Dll1/main.cpp
#include "plugin.h"
#include "main.h"
#include "stdio.h"
void _OnCycle() {
printf("Success\n");
}
extern "C" unsigned int PluginInit(PluginFuncs * pluginFuncs, PluginCallbacks * pluginCalls, PluginInfo * pluginInfo) {
printf("PluginInit called\n");
pluginCalls->OnCycle = _OnCycle;
return 1;
}
//Project: Dll1
//file: Dll1/Dll1/main.h
#define EXPORT __declspec(dllexport)
#include "plugin.h"
#ifdef __cplusplus
extern "C" {
#endif
EXPORT unsigned int PluginInit(PluginFuncs* pluginFuncs, PluginCallbacks* pluginCalls, PluginInfo* pluginInfo);
#ifdef __cplusplus
}
#endif
//Project: Dll1
//file: Dll1/Dll1/plugin.h
#pragma once
#include <stdint.h>
typedef struct _Settings {
uint32_t structSize;
uint32_t flags;
} Settings;
typedef struct _PluginInfo {
uint32_t structSize;
char name[32];
} PluginInfo;
typedef struct _PluginFuncs {
uint32_t structSize;
uint32_t(*GetVersion) (void);
}PluginFuncs;
typedef struct {
uint32_t structSize;
void (*OnCycle) ();
}PluginCallbacks;
It builds but crashes on execution.
//Output
C:\Users\[hidden]\source\repos\Dll1\Release>ConsoleAPplication1
Loading first dll
PluginInit called
PluginInit(a,b,c) returned 1
Now going to call OnCycle
C:\Users\[hidden]\source\repos\Dll1\Release>
See, it crashes as 'Done' message not printed.
How this is to be done correctly.?
It seems my problem is solved by creating a pointer, malloc'ing it and passing it to dll.
Here is the piece of code
PluginFuncs* a = NULL;
PluginCallbacks* b = NULL;
PluginInfo* c = NULL;
a = (PluginFuncs*)malloc(sizeof(PluginFuncs));
b = (PluginCallbacks*)malloc(sizeof(PluginCallbacks));
c= (PluginInfo*)malloc(sizeof(PluginInfo));
std::cout << "PluginInit(a,b,c) returned " << funci(a,b, c) << "\n";
std::cout << "Now going to call OnCycle\n";
if (b && b->OnCycle)
b->OnCycle();
std::cout << "Done";
and output
Loading first dll
PluginInit(a,b,c) returned 1
Now going to call OnCycle
Success
Done
Thanks

C++ compile error messages

So I have this code that I have to edit a bit but the code itself doesn't compile when I try in mobaxterm and since I don't really have much experience with C++ I hope u guys can help. This is the code:
//critical_example2.c
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "se207_sems.h"
int main(int argc, char argv[]){
//Use our source file as the "key"
int id=se207_semget("critical_example2.c",1);
int pid=fork();
if(pid){
//P1
while(1){
se207_wait(id);
printf("In critical section P1 ... \n");
rsleep();
printf("Ending critical section P1 ... \n");
se207_signal(id);
}
}else{
//P2
while(1){
se207_wait(id);
printf("In critical section P2 ... \n");
rsleep();
printf("Ending critical section P2 ... \n");
se207_signal(id);
}
}
}
This are the errors i get:
toneve#hvs-its-lnx01:~$ gcc critical_example2.c
In file included from critical_example2.c:9:0:
se207_sems.h: In function ‘se207_wait’:
se207_sems.h:91:6: warning: type of ‘id’ defaults to ‘int’ [-Wimplicit-int]
void se207_wait(id){
^
se207_sems.h: In function ‘se207_signal’:
se207_sems.h:95:6: warning: type of ‘id’ defaults to ‘int’ [-Wimplicit-int]
void se207_signal(id){
This might be the problematic code:
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
void rsleep(){
//Random sleep function. Comes in handy demoing stuff.
int stime=2+(rand()/(float)(RAND_MAX))*4;
printf("Sleeping for %d secs\n",stime);
sleep(stime);
}
int se207_semget(char* path, int val){
//Very simple semaphore "getting",
//always uses 1 as the project ID
//takes path to file and initial value of semaphore
int id; /* Number by which the semaphore
is known within a program */
union semun {
int val;
struct semid_ds *buf;
ushort * array;
} argument;
argument.val = val;
/* Create the semaphore with external key from
ftok if it doesn't already
exist. Give permissions to the world. */
id = semget(ftok(path,1), 1, 0666 | IPC_CREAT);
/* Always check system returns. */
if(id < 0)
{
fprintf(stderr, "Unable to obtain semaphore.\n");
exit(0);
}
/* Set the value of the number 0 semaphore in semaphore array # id
to the value "val". */
if( semctl(id, 0, SETVAL, argument) < 0)
fprintf( stderr, "Cannot set semaphore value.\n");
else
fprintf(stderr, "Semaphore %d initialized with path '%s'.\n",
ftok(path,1),path);
return id;
}
void se207_semop(int id,int val){
struct sembuf operations[1];
int retval; /* Return value from semop() */
//simple wait on semaphore
operations[0].sem_num = 0;
/* Which operation? Subtract 1 from semaphore value to wait, add to
signal */
operations[0].sem_op = val;
operations[0].sem_flg = 0;
retval = semop(id, operations, 1);
}
int void se207_wait(id){
se207_semop(id,-1);
}
int void se207_signal(id){
se207_semop(id,1);
}
Remove the int from your se207_wait and se207_signal functions, and declare id as an int in the parameter list.
void se207_wait(int id){
se207_semop(id,-1);
}
void se207_signal(int id){
se207_semop(id,1);
}

Issue getting functions from library and strange conversion error

I'm trying to write an arduino library. I've written a few classes before but nothing for arduino. I'm running into one error pretty consistently. First let me show you the code:
Code
Main.ino (The arduino project)
#include <Wire.h>
#include "Mobility.h"
Mobility mol = new Mobility();
void setup() {
Serial.begin(9600);
Wire.begin();
}
void loop() {
Serial.println("loop");
mol.move(true, 125, false, 125, 10);
delay(2000);
}
Mobility.h
#ifndef MOBILITY_H
#define MOBILITY_H
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
const int DEFAULT_MOBILITY_ADD = 4;
class Mobility
{
public:
void begin();
void begin(int address);
int i2cAdd;
int move(bool lPos, unsigned char leftPower, bool rPos, unsigned char rightPower, unsigned char msec);
private:
};
/**/
#endif
Mobility.cpp
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "Mobility.h"
#include "Wire.h"
void Mobility::begin(){
Wire.begin();
this.i2cAdd = DEFAULT_MOBILITY_ADD;
}
void Mobility::begin(int address){
Wire.begin();
this.i2cAdd = address;
}
int Mobility::move(bool lPos, unsigned char leftPower,bool rPos, unsigned char rightPower, unsigned char msec){
if (leftPower < -255 || leftPower > 255){
return -1;
}
if (rightPower < -255 || rightPower > 255){
return -2;
}
if(msec <= 0){
return -3;
}
Wire.beginTransmission(this.i2cAdd);
Wire.write(lPos);
Wire.write(leftPower);
Wire.write(rPos);
Wire.write(rightPower);
Wire.write(msec);
Wire.endTransmission();
return 0;
}
ERRORS
I've been getting two big errors while I've been trying to fix the code. The first is:
error: conversion from 'Mobility*' to non-scalar type 'Mobility' requested
Mobility mol = new Mobility();
The problem is caused by this line:
Mobility mol = new Mobility();
the first part is static memory allocation:Mobility mol - statically allocates memory for the object mol.
the second part uses dynamic memory allocation: new - dynamically allocates memory.
So you can do :
Mobility mol;// static allocation
or
Mobility *mol = new Mobility(); //dynamic allcocation
But not a mix of the two. Either way the constructor will be called when creating the object.

Field '__jmpbuf' could not be resolved -cpp

I get this error when trying to compile my program:
Field '__jmpbuf' could not be resolved
I looked for a solution for hours and can't seem to find out where is the culprit.
The Thread.h file contains the header of the class. It has the private member:
sigjmp_buf _env;
And the implementation is inside Thread.cpp:
#include "Thread.h"
#include <setjmp.h>
#include "translateAdd.h"
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#define COUNTER_INIT -1
int Thread::_idCounter = COUNTER_INIT;
Thread::Thread(void (*threadsFunc)(void))
: threadsFunction(threadsFunc), _stack(new char[STACK_SIZE]), _quantums(1)
{
address_t sp, pc;
sp = (address_t)_stack + STACK_SIZE - sizeof(address_t);
pc = (address_t)threadsFunc;
// set environment for later return
sigsetjmp(_env, 1);
(_env->__jmpbuf)[JB_SP] = translate_address(sp);
(_env->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&_env->__saved_mask);
_id = ++_idCounter;
_state = READY;
}
EDIT: Using eclipse as the IDE under ubuntu 32bit
EDIT: Another complete example that doesn't compile on my machine:
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#define SECOND 1000000
#define STACK_SIZE 4096
char stack1[STACK_SIZE];
char stack2[STACK_SIZE];
sigjmp_buf env[2];
#ifdef __x86_64__
/* code for 64 bit Intel arch */
typedef unsigned long address_t;
#define JB_SP 6
#define JB_PC 7
/* A translation is required when using an address of a variable.
Use this as a black box in your code. */
address_t translate_address(address_t addr)
{
address_t ret;
asm volatile("xor %%fs:0x30,%0\n"
"rol $0x11,%0\n"
: "=g" (ret)
: "0" (addr));
return ret;
}
#else
/* code for 32 bit Intel arch */
typedef unsigned int address_t;
#define JB_SP 4
#define JB_PC 5
/* A translation is required when using an address of a variable.
Use this as a black box in your code. */
address_t translate_address(address_t addr)
{
address_t ret;
asm volatile("xor %%gs:0x18,%0\n"
"rol $0x9,%0\n"
: "=g" (ret)
: "0" (addr));
return ret;
}
#endif
void switchThreads(void)
{
static int currentThread = 0;
int ret_val = sigsetjmp(env[currentThread],1);
printf("SWITCH: ret_val=%d\n", ret_val);
if (ret_val == 1) {
return;
}
currentThread = 1 - currentThread;
siglongjmp(env[currentThread],1);
}
void f(void)
{
int i = 0;
while(1){
++i;
printf("in f (%d)\n",i);
if (i % 3 == 0) {
printf("f: switching\n");
switchThreads();
}
usleep(SECOND);
}
}
void g(void)
{
int i = 0;
while(1){
++i;
printf("in g (%d)\n",i);
if (i % 5 == 0) {
printf("g: switching\n");
switchThreads();
}
usleep(SECOND);
}
}
void setup(void)
{
address_t sp, pc;
sp = (address_t)stack1 + STACK_SIZE - sizeof(address_t);
pc = (address_t)f;
sigsetjmp(env[0], 1);
(env[0]->__jmpbuf)[JB_SP] = translate_address(sp);
(env[0]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&env[0]->__saved_mask);
sp = (address_t)stack2 + STACK_SIZE - sizeof(address_t);
pc = (address_t)g;
sigsetjmp(env[1], 1);
(env[1]->__jmpbuf)[JB_SP] = translate_address(sp);
(env[1]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&env[1]->__saved_mask);
}
int main(void)
{
setup();
siglongjmp(env[0], 1);
return 0;
}
If you really need to use the internal fields (which will only be valid for your compiler on your system) you need to check the types:
typedef struct __jmp_buf_tag sigjmp_buf[1];
That means that sigjmp_buf is not a pointer, but an array with a single structure in it. So you use it like a normal array of structures:
sigjmp_buf _env;
_env[0].__jmpbuf[x] = y;
I really recommend against the use the internal field of this structure. Linux have other functions to simplify cooperative threading (which is what you seem to be implementing).

Is there a windows concurrency_queue.h equivalent on linux?

Well I am tryng to have a queue which is concurrent, but concurrency_queue isn't standard C++ and it's for windows, linux doesn't have it. Is there anything for linux like this (with the same functions like in the windows equivalent?)?
Edit:
This is needed to port this windows code to linux:
#include <concurrent_queue.h>
#ifdef defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#define SLEEP(x) { Sleep(x); }
#include <windows.h>
#include <process.h>
#define OS_WINDOWS
#define EXIT_THREAD() { _endthread(); }
#define START_THREAD(a, b) { _beginthread( a, 0, (void *)( b ) ); }
#else
#include <pthread.h>
#define sscanf_s sscanf
#define sprintf_s sprintf
#define EXIT_THREAD() { pthread_exit( NULL ); }
#define START_THREAD(a, b) { pthread_t thread;\
pthread_create( &thread, NULL, a, (void *)( b ) ); }
#endif
using namespace std;
using namespace Concurrency;
struct QuedData
{
int start;
int end;
int extraid;
AMX * script;
QuedData(){start = 0;end = 0;extraid = 0;script = NULL;}
QuedData(int start_,int end_,int extraid_, AMX * script_){start = start_;end = end_;extraid = extraid_;script = script_;}
};
struct PassData //thanks to DeadMG for improvements.
{
std::vector<cell> Paths;
int extraid;
AMX * script;
cell MoveCost;
PassData(){extraid = 0;script = NULL;MoveCost = 0;Paths.clear();}
template<typename Iterator> PassData(Iterator begin, Iterator end, int extraid_, cell MoveCost_, AMX * script_)
: Paths(begin, end)
{extraid = extraid_;MoveCost = MoveCost_;script = script_;}
~PassData(){Paths.clear();}
};
concurrent_queue <QuedData> QueueVector;
concurrent_queue <PassData> PassVector;
PassData LocalPass;
void PLUGIN_CALL
ProcessTick()
{
if(PassVector.try_pop(LocalPass))
{
amx_Push(LocalPass.script, LocalPass.MoveCost);
//blabla
}
}
static cell AMX_NATIVE_CALL n_CalculatePath( AMX* amx, cell* params )
{
QueueVector.push(QuedData(params[1],params[2],params[3],amx));
return 1;
}
bool PLUGIN_CALL Load( void **ppData )
{
START_THREAD( Thread::BackgroundCalculator, 0);
return true;
}
QuedData RecievedData;
vector <cell>tbcway;
cell tbccostx;
#ifdef OS_WINDOWS
void Thread::BackgroundCalculator( void *unused )
#else
void *Thread::BackgroundCalculator( void *unused )
#endif
{
while( true ){
if(QueueVector.try_pop(RecievedData)){
dgraph->findPath_r(xNode[RecievedData.start].NodeID ,xNode[RecievedData.end].NodeID,tbcway,tbccostx);
PassVector.push(PassData(tbcway.begin(),tbcway.end(),RecievedData.extraid,tbccostx,RecievedData.script));
}
SLEEP(5);
}
EXIT_THREAD();
}
The Visual C++ concurrent_queue is actually based on the Intel Threading Building Block Library
(If you open concurrent_queue.h header file in VC++ you will see an acknowledgement)
You can get the library from
http://threadingbuildingblocks.org/
The library will run on Linux as well.
I think threadpool does this or an unofficial Boost enhancement called lockfree and should by now be part of Boost::Atomics. I haven't use both but let us know if you have any luck.
I would suggest looking at https://github.com/romanek-adam/boost_locking_queue for the code and the article that goes with it at Implementing a Thread-Safe Queue using Condition Variables