so i am using jansson library and i want to set a value:
json_object_set_new(event, "error_code", json_integer(response->error_code));
The problem is that, i need to free response struct, but still use the value i have set in json_object_set_new.
Should i copy the value from response->error_code and how can i do that?
Some context:
plugin_response: {
if(!response->message && response->error_code == 0) {
response->error_code = JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR;
if(response->error_cause == NULL) {
response->error_cause = g_strdup_printf("%s", "Invalid response");
}
}
json_t *event = json_object();
if(!response->message && response->error_code != 0) {
/* Prepare JSON error event */
json_object_set_new(event, "audiobridge", json_string("event"));
json_object_set_new(event, "error_code", json_integer(response->error_code));
json_object_set_new(event, "error", json_string(response->error_cause));
} else {
event = json_deep_copy(response->message);
}
if(root != NULL)
json_decref(root);
if(jsep != NULL)
json_decref(jsep);
g_free(transaction);
g_free(response);
return janus_plugin_result_new(JANUS_PLUGIN_OK, NULL, event);
}
EDIT: I am also using GLib, so if there is a nifty method for this, i am all ears.
Okey, i read this This article and i understood. I don't need to copy integer i am passing to json_integer(), because it's is not a pointer and is completely isolated from the structs integer.
Related
I'm writing an auto display turn-off function with ESP32 on Arduino framework with PIO.
I have a Screen class for handling all of the screen functions.
void Screen::turn_off_screen(){
digitalWrite(SCREEN_ENABLE, LOW);
}
void turn_off_screen_wrapper()
{
Serial.println("turn_off_screen_wrapper called");
if (c_screen_Instance != nullptr)
{
c_screen_Instance->turn_off_screen();
}
}
void Screen::auto_display_power_off(int timeout){
Serial.println("auto_display_power_off called");
c_screen_Instance = this;
auto_off_timer = timerBegin(0, 80, true);
Serial.println("auto_off_timer ran");
timerAttachInterrupt(auto_off_timer, &turn_off_screen_wrapper, true);
Serial.println("timerAttachInterrupt ran");
//Converts given seconds from us to seconds
timerAlarmWrite(auto_off_timer,timeout*1000000,false);
timerAlarmEnable(auto_off_timer);
}
The code compiles however I get this when I run it on the board.
auto_display_power_off called
[E][esp32-hal-cpu.c:93] addApbChangeCallback(): duplicate func=400811F8 arg=3FFBDC54
auto_off_timer ran
The screen never gets turned off of course since the callback never runs. Any ideas why this is happening?
is c_screen_Instance global?
is auto_off_timer global?
Consider providing a bit more of your code.
But anyway.
bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
initApbChangeCallback();
apb_change_t * c = (apb_change_t*)malloc(sizeof(apb_change_t));
if(!c){
log_e("Callback Object Malloc Failed");
return false;
}
c->next = NULL;
c->prev = NULL;
c->arg = arg;
c->cb = cb;
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
if(apb_change_callbacks == NULL){
apb_change_callbacks = c;
} else {
apb_change_t * r = apb_change_callbacks;
// look for duplicate callbacks
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
if (r) {
log_e("duplicate func=%8p arg=%8p",c->cb,c->arg);
free(c);
xSemaphoreGive(apb_change_lock);
return false;
}
else {
c->next = apb_change_callbacks;
apb_change_callbacks-> prev = c;
apb_change_callbacks = c;
}
}
xSemaphoreGive(apb_change_lock);
return true;
}
This is addApbChangeCallback's declaration.
Your error comes from this line :
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
Where r it's a struct to hold all the callbacks.
This error indeed indicates this callback function was already assigned somewhere in your code. r is global, so your code is re-assigning the same callback twice.
Try to either only assign it once, or to unassign the function before assigning it again with removeApbChangeCallback(void * arg, apb_change_cb_t cb) or timerDetachInterrupt
I've also found a reported issue related to timerAttach on the current version here: https://github.com/espressif/arduino-esp32/issues/6730
Try to roll back the Platform PIO's version to a more stable one:
# instead of espressif32
platform = https://github.com/platformio/platform-espressif32.git#<tag-version>
Check on the git link for the available tags you can use.
Problem was that I was attaching the interrupt in the void loop(). Which would run way faster than the actual timer. After moving it to setup (Setup being a placeholder) I plan on having it on a Hardware interrupt it worked as expected.
I have the following method in C to load a binary file, it seems rather long and tedious having to check the error value from each and every fread call, is there a neater way to handle this?
I'm aware that some of the calls could be reduced by reading in a struct in one go, but due to how C can add padding bytes in between struct members, I'd prefer to avoid this.
some_type_t *load_something(FILE *file) {
some_type_t *something = (some_type_t *)malloc(sizeof(some_type_t));
if (something == NULL) {
return NULL;
}
if (fread(&something->field1, sizeof(something->field1), 1, file) == 0) {
free(something);
return NULL;
}
if (fread(&something->field2, sizeof(something->field2), 1, file) == 0) {
free(something);
return NULL;
}
if (fread(&something->field3, sizeof(something->field3), 1, file) == 0) {
free(something);
return NULL;
}
uint16_t some_var1, some_var2, some_var3;
some_other_type_t *something_else1 = (some_other_type_t *)malloc(sizeof(some_other_type_t));
if (fread(&some_var1, sizeof(some_var1), 1, file) == 0) {
free(something);
free(something_else1);
return NULL;
}
some_other_type_t *something_else2 = (some_other_type_t *)malloc(sizeof(some_other_type_t));
if (fread(&some_var2, sizeof(some_var2), 1, file) == 0) {
free(something);
free(something_else1);
free(something_else2);
return NULL;
}
some_other_type_t *something_else3 = (some_other_type_t *)malloc(sizeof(some_other_type_t));
if (fread(&some_var3, sizeof(some_var3), 1, file) == 0) {
free(something);
free(something_else1);
free(something_else2);
free(something_else3);
return NULL;
}
// Do something with the vars and allocated something elses.
// ...
return something;
}
Why not creating a macro:
#define READ_FIELD(data) \
do { if (fread(&data, sizeof(data), 1, file) == 0) { \
free(something); \
free(something_else1);
free(something_else2);
return NULL; \
} } while(0)
then call it like a function call:
READ_FIELD(something->field1);
READ_FIELD(something->field2);
READ_FIELD(some_var1);
READ_FIELD(some_var2);
the code will be the same but at least it is now generated and not copied/pasted (with possible errors).
The macro has to call free on all possible memory blocks, even the ones that aren't allocated yet. The only constraint is to set the unallocated ones to NULL so free doesn't crash. And to be super safe change as:
free(something); something = NULL;
(of course if something is the copy of an allocated pointer, setting to NULL doesn't protect against double free, it has limits)
you can apply this technique to the write side as well, and since M Oehm suggested that, you could make a list of what you want to read/write in a wrapper macro:
#define DO_ALL \
DO_FIELD(something->field1); \
DO_FIELD(something->field2); \
DO_FIELD(some_var1); \
DO_FIELD(some_var2)
then define DO_FIELD as READ_FIELD or WRITE_FIELD:
#define DO_FIELD READ_FIELD
DO_ALL;
#undef DO_FIELD
There's nothing that could save you to check the success of each and every call, but you can improve on the code structure using goto (this is in fact one idiomatic use of goto in C, pseudo-code to follow):
if (first_call() < 0) goto error;
if (second_call() < 0) goto error;
// [...]
// when everything succeeded:
return result;
error:
// free resources
// return error-indicator, e.g.
return 0;
If the resources to free accumulate over the course of your function, make sure to first initialize them all to NULL/0 (assuming they are pointers). Then, calling free() on them in your error part has no effect when they're not allocated yet. If you use own "destructor functions", make sure to design them the same way free() is designed -- when passed a NULL value, it should be a no-op.
You need to initialize all something pointers to NULL and centralise the cleaning up at one place.
...
something = something_else1 = something_else2 = something_else3 = NULL;
...
some_other_type_t *something_else3 = (some_other_type_t *)malloc(sizeof(some_other_type_t));
if (fread(&some_var3, sizeof(some_var3), 1, file) == 0) {
goto error;
}
// Do something with the vars and allocated something elses.
// ...
return something;
error:
free(something);
free(something_else1);
free(something_else2);
free(something_else3);
return NULL;
}
Freeing a NULL pointer is OK, it does nothing, therefore you don't need to check if the someting pointers are NULL before calling free.
Sidenote: in C you don't cast the return value of malloc.
Here is a simple way to group the malloc and fread operations and check just once for proper completion:
some_type_t *load_something(FILE *file) {
uint16_t some_var1, some_var2, some_var3;
some_type_t *something = malloc(sizeof(*something));
some_other_type_t *something_else1 = malloc(sizeof(*something_else1));
some_other_type_t *something_else2 = malloc(sizeof(*something_else2));
some_other_type_t *something_else3 = malloc(sizeof(*something_else3));
if (!something || !something_else1 || !something_else2 || !something_else3 ||
!fread(&something->field1, sizeof(something->field1), 1, file) ||
!fread(&something->field2, sizeof(something->field2), 1, file) ||
!fread(&something->field3, sizeof(something->field3), 1, file) ||
!fread(&some_var1, sizeof(some_var1), 1, file) ||
!fread(&some_var2, sizeof(some_var2), 1, file) ||
!fread(&some_var3, sizeof(some_var3), 1, file))
{
free(something);
free(something_else1);
free(something_else2);
free(something_else3);
return NULL;
}
// Do something with the vars and allocated something elses.
// ...
return something;
}
Note that passing a null pointer to free() is OK.
I love python and want to contribute. I came across this line in the cpython source code.
for (;;) {
item = iternext(it);
if (item == NULL)
break;
cmp = PyObject_IsTrue(item);
Py_DECREF(item);
if (cmp < 0) {
Py_DECREF(it);
return NULL;
}
if (cmp > 0) {
Py_DECREF(it);
Py_RETURN_TRUE;
}
}
What's the point of using for(;;) and
if (item == NULL)
break;
instead of while(item!=NULL) is it because the programmer wants iternext(it) to be executed at least once? This doesn't seem very intuitive to me but since its python source code I believe there must be a good reason?
This is a loop that is exited in the middle. To make it a while loop that behaves identically, you would have to write
item = iternext(it);
while (item != NULL) {
cmp = PyObject_IsTrue(item);
Py_DECREF(item);
if (cmp < 0) {
Py_DECREF(it);
return NULL;
}
if (cmp > 0) {
Py_DECREF(it);
Py_RETURN_TRUE;
}
item = iternext(it);
}
but that means duplicating one line; it also places the second iternext far away from the while statement, thus making the connection less obvious.
i'm trying to develop an application (written in ANSI C) for an OpenWrt router using libuci.
I've read this useful post: How to find out if the eth0 mode is static or dhcp?
and i've develop a piece of my application that is able to read network data (in this case i read if ppp is enabled) using uci library.
char path[]="network.ppp.enabled";
struct uci_ptr ptr;
struct uci_context *c = uci_alloc_context();
if(!c) return;
if (strcmp(typeCmd, "GET") == 0){
if ((uci_lookup_ptr(c, &ptr, path, true) != UCI_OK) || (ptr.o==NULL || ptr.o->v.string==NULL)) {
uci_free_context(c);
return;
}
if(ptr.flags & UCI_LOOKUP_COMPLETE)
strcpy(buffer, ptr.o->v.string);
uci_free_context(c);
printf("\n\nUCI result data: %s\n\n", buffer);
}
now i want try to SET new network data (so i want enable ppp -> set ppp to 1)
I've write:
}else if (strcmp(typeCmd, "SET") == 0){
if ((uci_lookup_ptr(c, &ptr, path, true) != UCI_OK) || (ptr.o==NULL || ptr.o->v.string==NULL)) {
uci_free_context(c);
return;
}
ptr.o->v.string = "1";
if ((uci_set(c, &ptr) != UCI_OK) || (ptr.o==NULL || ptr.o->v.string==NULL)) {
uci_free_context(c);
return;
}
if (uci_commit(c, struct uci_package **p, true) != UCI_OK){
uci_free_context(c);
return;
}
}
LibUci documentation is non-existent, there is just some info in the file uci.h, i don't know how fill uci_ptr struct, so i've retrieve it from uci_lookup_ptr , i've change ptr.o->v.string and launch uci_set with new params, but about uci_commit i don't know about struct uci_package **p.
Someone call share with me a bit of documentation or show me some examples?
Thanks a lot
The documentation is very thin on UCI. The way I figured it out is by using the uci_ptr's .value property from the uci structure.
Fromt that, I change the line:
ptr.o->v.string = "1";
to:
ptr.value = "1";
I also changed your commit line as follows:
uci_commit(ctx, &ptr.p, false);
That worked for me.
I'm trying to debug some code that uses COM, which I am a beginner at.
The two calls to IUnknown::Release at the end have got me worried.
The interfaces were created with DllGetClassObject and IClassFactory::CreateInstance.
I have seen other similar code that does not call IUnknown::Release on these - which is correct?
int OpenMixer_Win_DirectSound(px_mixer *Px, int index)
{
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA desc;
HMODULE hDsound = INVALID_HANDLE_VALUE;
GCO DllGetClassObject;
IClassFactory *pcf = NULL;
IKsPropertySet *pps = NULL;
HRESULT hr;
ULONG bytes;
LPGUID guidIn;
LPGUID guidOut;
UINT deviceIn = -1;
UINT deviceOut = -1;
int ret = FALSE;
guidIn = PaWinDS_GetStreamInputGUID(Px->pa_stream);
guidOut = PaWinDS_GetStreamOutputGUID(Px->pa_stream);
do {
hDsound = LoadLibraryA("dsound.dll");
if (hDsound == NULL) {
break;
}
DllGetClassObject = (GCO) GetProcAddress(hDsound, "DllGetClassObject");
if (DllGetClassObject == NULL) {
break;
}
hr = DllGetClassObject(&CLSID_DirectSoundPrivate,
&IID_IClassFactory,
(void **)(&pcf));
if (hr || pcf == NULL) {
break;
}
hr = IClassFactory_CreateInstance(pcf,
NULL,
&IID_IKsPropertySet,
(void **)(&pps));
if (hr || pps == NULL) {
break;
}
/* Do stuff with the interfaces */
} while( FALSE );
if (pps) {
IUnknown_Release(pps);
}
if (pcf) {
IUnknown_Release(pcf);
}
// Free the library. Note that portaudio also opens dsound.dll
// so this probably doesn't do anything until Pa_Terminate is called.
if (hDsound != INVALID_HANDLE_VALUE) {
FreeLibrary(hDsound);
}
}
Absolutely. Both functions create a new interface pointer, they will have a reference count of 1, the AddRef() function was already called. When you're done with it then you have to call Release(). You'll leak memory if you don't. Every interface in COM works this way.
Yes. As seen in DllGetClassObject sample, the return ppvObj will have a refcount.
Yes, DllGetClassObject() will create an object and pass ownership of that object to your code. Your code will now own the object and be responsible for releasing it by calling IUnknown::Release().