Iam new to using Core Foundations. I want to use dictionary to store some key value pair. The value must be a pointer to a struct. This pointer is pointing to dynamically allocated buffer.
CFMutableDictionaryRef init_hash_table() {
return CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
This is used to create the dictionary and the return value is stored as global variable.
CFNumberRef
create_hash_key(int sd) {
return CFNumberCreate(NULL, kCFNumberIntType, &sd);
}
int
add_hash_entry(CFMutableDictionaryRef dict, int sd, void *pkt) {
CFNumberRef key = create_hash_key(sd);
CFDictionarySetValue(dict, key, pkt);
return 0;
}
When I execute this code, I get segfault. I see that pkt has a valid address and key seems to be created. Does anyone know how to assign a pointer to value part?
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000011
0x00007fff8c9f339f in objc_msgSend_fixup ()
Any ideas?
The problem is the kCFTypeDictionaryValueCallBacks argument. From the documentation:
kCFTypeDictionaryValueCallBacks
Predefined CFDictionaryValueCallBacks structure containing a set of
callbacks appropriate for use when the values in a CFDictionary are
all CFType-derived objects.
So in your case, CFRetain() is called on the pointer when the value is added to the
dictionary. This causes the crash because the pointer does not point to a CoreFoundation
object.
You can create the dictionary with
CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, NULL);
instead, so that no "reference counting" will be done on the value.
Alternatively, you can wrap the pointer into a CFDataRef and put that into the
dictionary.
In both cases it is your responsibility that the pointer is still valid
when the value is retrieved from the dictionary later.
Here is a simple example how you could implement refcounting for your custom objects:
typedef struct {
int refcount;
int val;
} mystruct;
const void *myretain(CFAllocatorRef allocator, const void *value)
{
mystruct *p = (mystruct *)value;
p->refcount++;
return p;
}
void myrelease(CFAllocatorRef allocator, const void *value)
{
mystruct *p = (mystruct *)value;
if (p->refcount == 1)
free(p);
else
p->refcount--;
}
int main(int argc, const char * argv[])
{
mystruct *p = malloc(sizeof(*p));
p->refcount = 1;
p->val = 13;
CFDictionaryValueCallBacks vcb = { 0 , myretain, myrelease, NULL, NULL };
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &vcb);
int sd = 13;
CFNumberRef key = CFNumberCreate(NULL, kCFNumberIntType, &sd);
CFDictionarySetValue(dict, key, p);
// refcount == 2
myrelease(NULL, p);
// refcount == 1
mystruct *q = CFDictionaryGetValue(dict, key);
// refcount is still 1, "GetValue" does not increment the refcount
CFRelease(dict);
// object is deallocated
return 0;
}
Related
I've been trying for a long time to pass an array of objects to another class object.
In settingUp.cpp:
//** Status classes and their functions **//
void settingUp(){
dataClass prueba0;
dataClass prueba1;
dataClass prueba2;
const dataClass * arrayPrueba[3];
prueba0.setValues(1);
prueba1.setValues(2);
prueba2.setValues(3);
arrayPrueba[0] = &prueba0;
arrayPrueba[1] = &prueba1;
arrayPrueba[2] = &prueba2;
statusClass status;
status.setValues(1, arrayPrueba);
status.printValues();
}
In classData.cpp:
//** dataClass and their functions **//
void dataClass::setValues(int _length){
length = _length;
}
void dataClass::printValues() const{
printf("TP: dataClass: length = %d\n", &length);
};
In statusClass.cpp:
//** Status classes and their functions **//
void statusClass::setValues (uint8_t _statusSelectorByte, const dataClass **_array){
newStatusSelectorByte = _statusSelectorByte;
array = *_array;
};
void statusClass::printValues(){
printf("TP: statusClass -> printValues: Prueba = %d\n", newStatusSelectorByte);
printf("TP: statusClass -> printValues: arrayPrueba = %d\n", array[1].length);
}
When I call:
status.printValues();
I can read only the fist element of the arrayPrueba.
In statusClass::setValues(), *_array is the same as _array[0]. You are storing only the first dataClass* pointer from the input array.
Later, when using array[1], you are mistreating array as-if it were a pointer to an array of objects, when it is really a pointer to a single object instead. You are thus reaching past that object into surrounding memory, which is undefined behavior (but may "work" in this case because an object may happen to actually exist at that location, but this is bad behavior to rely on).
You need to store the original array pointer, not a single element taken from the array.
private:
const dataClass **array; // <-- add an *
void statusClass::setValues (uint8_t _statusSelectorByte, const dataClass **_array){
newStatusSelectorByte = _statusSelectorByte;
array = _array; // <-- get rid of the *
};
void statusClass::printValues(){
printf("TP: statusClass -> printValues: Prueba = %d\n", newStatusSelectorByte);
printf("TP: statusClass -> printValues: arrayPrueba = %d\n", array[1]->length); // use -> instead of .
}
On a side note: in dataClass::printValues(), you need to drop the & when printing the value of length:
printf("TP: dataClass: length = %d\n", length);
I have a map structure as below which has shared_pointer of a protobuf structure Stats:
map<string, shared_pointer<vol::proto::Stats> statsMap;
I am storing and retrieving the map entries through a LRU cache implementation
template class LRUCache<string,std::shared_ptr<vol::proto::Stats>>;
Protobuf structure:-
message Stats {
required string oid = 1;
required int64 logical_size = 2;
required int64 committed_size = 3;
}
message StatsRequest {
required string uuid = 1;
}
The function for storing entry into the map:-
template<class K, class V>
void
LRUCache<K, V>::Put(const K& key, V value)
{
Vmacore::System::WriteSynchronized lock(this);
auto val = refMap.find(key);
if (val == refMap.end()) {
if (cacheSize == refMap.size()) {
K leastUsedKey = lruList.back();
lruList.pop_back();
refMap.erase(leastUsedKey);
}
} else {
lruList.erase(val->second.lruKeyRef);
}
lruList.push_front(key);
refMap[key] = LRUValueReference<K, V>(lruList.begin(), value);
}
void PutS(const string& Id, const vol::proto::Stats& info)
{
shared_ptr<vol::proto::Stats> statsInfo = make_shared<vol::proto::Stats>(info);
_StatsCache.Put(Id, statsInfo);
}
void PutStats(vol::proto::StatsRequest &req) {
vol::proto::Stats *stats;
GetStats(stats); //stats gets populated here.
PutS(stats->oid(), *stats);
}
To Get the entry from the map:-
template<class K, class V>
bool
LRUCache<K, V>::Get(const K& key, V& value)
{
Vmacore::System::WriteSynchronized lock(this);
auto val = refMap.find(key);
if (val == refMap.end()) {
return false;
}
lruList.splice(lruList.begin(), lruList, val->second.lruKeyRef);
val->second.lruKeyRef = lruList.begin();
value = val->second.value;
return true;
}
void GetS(const string& Id, shared_ptr<vol::proto::Stats> info)
{
if (!_StatsCache.Get(Id, info))
return false;
return true;
}
void GetStats(vol::proto::StatsRequest &req) {
shared_ptr<vol::proto::Stats> stats;
if (GetS(req.uuid(), stats)) {
Log("object id is %s", stats.get()->oid()); // Crash at oid (this=0x0)
}
}
Now while doing GetStats, I am seeing a crash as to in GetStats's Log statement that is program terminated with signal SIGSEGV, Segmentation fault. Should I do a make_share for Stats in GetStats? Can you please describe as to what has caused this crash and how to fix the crash here?
You're passing a raw pointer from GetStats to GetS, which then wraps it into a shared_ptr. Now lets start ref-counting.
GetS -> increase on entry > 1
_StatsCache.Get -> pass by ref > 1
GetS -> decrease on exit > 0
Ref count 0 -> delete the pointer.
In GetStats you then try to de-reference the stats pointer by calling .get, but it was just deleted.
You should either always use smart pointers, or be very very very careful when you convert from raw pointer to smart pointer, and back.
Actually what I wrote is wrong. What you're doing is actually much worse.
You're wrapping a raw pointer in GetS into a smart pointer, and then pass it by ref to your _StatsCache.Get, which then assigns a different shared_ptr to yours. So you've overwritten the original raw pointer with something else.
But when GetS returns, that shared_ptr is now lost and destructed, but the original stats pointer is accessed in stats.get(). What's in it? Nothing from GetS, that's for sure.
I am trying to generate a function call using AsmJit to which I pass an char*. This char* is in itself retrieved from another function call. I tried out this:
typedef
const char* getStr();
const char* getStrImpl() {
return "hello pie";
}
void use_str_impl(int id, const char* c_str) {
// do stuff...
}
int main() {
JitRuntime rt;
CodeHolder code;
code.init(rt.getCodeInfo());
X86Compiler c(&code);
auto jitted_func = c.addFunc(FuncSignature0<const char*>(code.getCodeInfo().getCdeclCallConv()));
auto err = c.getLastError();
auto call = c.call((uint64_t) fooFuncImpl, FuncSignature0<intptr_t>());
X86Gpd res(call->getRet().getId());
auto call2 = c.call((uint64_t) send_input, FuncSignature2<void, int, intptr_t>());
err = !call2->setArg(0, Imm(42));
err = !call2->setArg(1, res);
c.ret();
c.endFunc();
err = c.finalize();
if(err) return 0;
size_t size = code.getCodeSize();
VMemMgr vm;
void* p = vm.alloc(size);
if (!p) return 0;
code.relocate(p);
auto fun = (entrypoint*) p;
fun();
}
It turns out this does not generate any instructions for the second parameter or second call to setArg. I also tried to use .newIntPtr and using move instructions to move the result of call into place. But this generated dec and add instructions which made no sense to me and my small experience with assembly. What is the correct way of doing this type of thing?
Btw I am using the AsmJit next branch.
I have done few corrections to your sample with some comments.
Better Usage of JitRuntime:
JitRuntime rt;
size_t size = code.getCodeSize();
VMemMgr vm;
....
void* p = vm.alloc(size);
if (!p) return 0;
code.relocate(p);
auto fun = (entrypoint*) p;
You have used JitRuntime just to setup the parameters for CodeHolder, but then avoided it and allocated the memory for the function yourself. While that's a valid use case it's not what most people do. Using runtime's add() is sufficient in most cases.
Invalid use of CCFuncCall::getRet():
X86Gpd res(call->getRet().getId());
The call node at this point doesn't have any return register assigned so it would return an invalid id. If you need to create a virtual register you always have to call compiler's newSomething(). AsmJit's compiler provides API to check for that case at runtime, if you are unsure:
// Would print 0
printf("%d", (int)c.isVirtRegValid(call->getRet().getId()));
The solution is to create a new virtual register and ASSIGN it to the function's return value. Assigning return value requires an index (like assigning an argument), the reason is that some functions may return multiple values(like 64-bit value in 32-bit mode), using 0 as index is sufficient most of the time.
X86Gp reg = c.newIntPtr("reg");
call->setRet(0, reg);
You can verify getRet() functionality:
X86Gp reg = c.newIntPtr("reg");
assert(call->getRet(0).isNone());
call->setRet(0, reg);
assert(call->getRet(0) == reg);
Fully working example:
#include <stdio.h>
#include <asmjit/asmjit.h>
const char* func_a() {
printf("func_a(): Called\n");
return "hello pie";
}
void func_b(int id, const char* c_str) {
printf("func_b(%d, %s): Called\n", id, c_str);
}
int main() {
using namespace asmjit;
JitRuntime rt;
CodeHolder code;
code.init(rt.getCodeInfo());
X86Compiler c(&code);
X86Gp reg = c.newIntPtr("reg");
// Compilation step...
c.addFunc(FuncSignature0<void>(code.getCodeInfo().getCdeclCallConv()));
auto call_a = c.call((uint64_t)func_a, FuncSignature0<intptr_t>());
call_a->setRet(0, reg);
auto call_b = c.call((uint64_t)func_b, FuncSignature2<void, int, intptr_t>());
call_b->setArg(0, Imm(42));
call_b->setArg(1, reg);
c.ret();
c.endFunc();
// Finalize does the following:
// - allocates virtual registers
// - inserts prolog / epilog
// - assembles to CodeHolder
auto err = c.finalize();
if (err) {
printf("COMPILER FAILED: %s\b", DebugUtils::errorAsString(err));
return 1;
}
typedef void (*EntryPoint)(void);
EntryPoint entry;
// Adds function to the runtime. Should be freed by rt.release().
// Function is valid until the runtime is valid if not released.
err = rt.add(&entry, &code);
if (err) {
printf("RUNTIME FAILED: %s\b", DebugUtils::errorAsString(err));
return 1;
}
entry();
return 0;
}
I am trying to create a function that receives and returns a double. For the call method I used the approach with Mem. At the end I need to save the result in the variable xmm1.
I can't identify the error. The sine function is called correctly. But for the final assembler generation error occurs.
JitRuntime rt;
CodeHolder code;
code.init(rt.codeInfo());
asmjit::x86::Compiler cc(&code);
asmjit::x86::Gp reg = cc.newIntPtr("reg");
asmjit::Zone zonee(1024);
asmjit::ConstPool constPool(&zonee);
asmjit::Label constPoolLabel = cc.newLabel();
// Compilation step...
// c.addFunc(asmjit::FuncSignatureT<void>(code.codeInfo().getCdeclCallConv()));
cc.addFunc(asmjit::FuncSignatureT<void>());
auto call_a = cc.call((uint64_t)func_a, FuncSignatureT<intptr_t>());
call_a->setRet(0, reg);
auto call_b = cc.call((uint64_t)func_b, FuncSignatureT<void, int, intptr_t>());
call_b->setArg(0, Imm(42));
call_b->setArg(1, reg);
auto seno = [&](double value) {
size_t valueOffset;
double seno = static_cast<double_t>(std::sin(value));
cout << " seno " << seno << endl;
constPool.add(&seno, sizeof(double), valueOffset);
return asmjit::x86::ptr(constPoolLabel, valueOffset);
};
asmjit::x86::Mem mem;
double test = 180.5;
auto call_c = cc.call(seno(test), asmjit::FuncSignatureT<double_t>());
call_c->setArg(0, asmjit::Imm(test));
call_c->_setRet(0, mem);
cc.movsd(asmjit::x86::xmm1, mem);
cc.ret();
cc.endFunc();
// Finalize does the following:
// - allocates virtual registers
// - inserts prolog / epilog
// - assembles to CodeHolder
auto err = cc.finalize();
if (err) {
printf("COMPILER FAILED: %s\b", DebugUtils::errorAsString(err));
return;
}
typedef void (*EntryPoint)(void);
EntryPoint entry;
// Adds function to the runtime. Should be freed by rt.release().
// Function is valid until the runtime is valid if not released.
err = rt.add(&entry, &code);
if (err) {
printf("RUNTIME FAILED: %s\b", DebugUtils::errorAsString(err));
return;
}
entry();
return;
perhaps the memory object should relate to some memory address?
Mem mem = qword_ptr ((uint64_t) &test);
I want to create persistent nodes in ZooKeeper. To do this, I have these two functions:
void create_completion(int rc, const char * value, const void * data){
// empty callback at this moment
}
void create(const char * path, const char * value){
zoo_acreate(zh, path, value, 0, &ZOO_OPEN_ACL_UNSAFE, 0, create_completion, NULL);
}
What I find interesting, is that if I call create function from my main function and then just terminate, then no data is uploaded:
int main(){
... some code to initialize session
create("/newnode", ""); // node is not created
zookeeper_close(zh);
return 0;
}
Whereas if I do:
int main(){
... some code to initialize session
create("/newnode", ""); // node is created
bool flag = true;
while(flag){
usleep(10000000);
flag = false;
}
zookeeper_close(zh);
return 0;
}
then "/newnode" is uploaded to ZooKeeper. So, what is wrong with that and why do I really need this loop?
This code runs successfully and MQStruct constructor initialized the values as well, I can see in ExecuteThread function but in TestFunction, I get the garbage values for MQStruct.
I am passing address of struct "&MQStructObj" to _beginthreadex for parameters and This is the problem I guess
struct MQStruct {
MQStruct()
{
pointer=NULL;
serviceName=NULL;
durability=0;
msgType=0;
msgHeader=0;
msgId=NULL;
payload=NULL;
payloadSize=0;
ttl=0;
priority=0;
}
void* pointer;
wchar_t *serviceName;
int durability;
int msgType;
int msgHeader;
wchar_t *msgId;
wchar_t *payload;
int payloadSize;
int ttl;
int priority;
};
int ExecuteThread() {
HANDLE heartBeatThread;
unsigned int hbThreadID;
int result = 0;
MQStruct MQStructObj;
MQStructObj.pointer=this;
heartBeatThread = (HANDLE)_beginthreadex(NULL, 0 , &TestFunction, &MQStructObj, 0/*CREATE_SUSPENDED*/, &hbThreadID);
if ( heartBeatThread == 0 )
{
result = -1;
LogEvent(DEBUG_LOG,0, "Fail to create thread");
}
CloseHandle(heartBeatThread);
return result;
}
You guessed correctly.
You're passing the address of a local variable to your thread-proc-startup, then leaving scope (and destroying the object in the process). References to this object in your thread proc are there-after undefined behavior.
Dynamically allocate one with new and let the thread proc delete it.
MQStructObj is declared on the stack so will go out of scope and potentially be overwritten as soon as ExecuteThread completes.
If you want to use a stack object here, you'll need to add some synchronisation to allow your new thread to copy from MQStructObj before ExecuteThread returns.
Alternatively, normally preferably, you could allocate MQStructObj dynamically and leave the new thread to clean it up at its leisure
MQStruct* MQStructObj = new MQStruct();
MQStructObj->pointer=this;
heartBeatThread = (HANDLE)_beginthreadex(NULL, 0 , &TestFunction, MQStructObj, 0, &hbThreadID);
if ( heartBeatThread == 0 ) { // error
delete MQStructObj;
result = -1;
}
// ownership of MQStructObj transferred to new thread