How to check if a cJSON pointer was initialized/set earlier? - cjson

I have a struct with cJSON pointers as in:
struct {
cJSON *myJSON1;
cJSON *myJSON2;
...
} myStruct;
Somewhere in my code I create cJSON items as in myStruct.myJSON1 = cJSON_CreateObject()
At the end of the code, I want to call cJSON_Delete() on those pointers which were assigned. I presume this is the classic C case where there is no way to find out if the pointer was malloced in some way. Of course, I can keep a flag to keep track but I want a simple way. I read...
The cJSON struct is as:
/* The cJSON structure: */
typedef struct cJSON
{
struct cJSON *next;
struct cJSON *prev;
struct cJSON *child;
int type;
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
double valuedouble;
char *string;
} cJSON;
The function cJSON_Invalid() is available. The documentation states "(check with cJSON_IsInvalid): Represents an invalid item that doesn't contain any value. You automatically have this type if you set the item to all zero bytes." Do I have to memset the structure to 0 or just type?
In other words, my question is: What would be the easiest way to check if a cJSON pointer is malloced without creating an additional variable? Perhaps set "type" to zero? I can try such options but I want a definite answer which works in all situations.

If you just have an uninitialized pointer to a cJSON data structure the behavior is undefined.
I.e. for cJSON *myJSON1;
cJSON_Invalid(myJSON1) might return 0 or 1.
And cJSON_Delete(myJSON1) will probably segfault. Or do nothing if you get lucky.
The solution is to always initialize cJSON data structures to NULL.
Then you can just call cJSON_Delete(). If the pointer is still NULL the call will do nothing. If it was set up at some point in your program it will correctly release all the memory.
Since you have a structure of multiple cJSON pointers you can set the entire data structure to 0 using memset.
You can take a look at the source code.
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
{
cJSON *next = NULL;
while (item != NULL)
{
...
}
}

Related

How to get a void** to be a parameter of a C library?

I'm trying to call a C library from GO using cgo.
The C library has the following function:
int receive(void** data);
// I'd call it like that:
void* myptr; // myptr=null
int nbBytes = receive(&myptr);
if (nbBytes==0) { return }
// myptr has now an address to a valid buffer that contains nbBytes bytes.
// And then casting it with char* to access the data that can be anything. Example:
printf("%d", *(char*)myptr);
How can I call this receive() function from GO? Go doesn't allocate any memory, the memory address is returned via myptr and directly access from it.
receive() is a "no-copy" and writes the actual data's address into myptr. The data is then accessed using *(char*)myptr.
we can assume receive() allocates and frees the buffer, it's hidden from the lib's user
Ideally, I would read the data via []byte in go.
[Edit: you added a clarification that says this isn't just suggested. But we still don't know how the data are used afterward, from C code.]
There is not enough information in your question to answer it completely, because we don't know—the C language alone doesn't tell us—how this void ** is used. Your comments and additional code suggest (pretty strongly) that the way it's used is that receive fills in the pointer:
int receive(void **data) {
*data = <something>;
return <some value>;
}
where the angle-bracketed sections are unknown to us; to use this data from C code, we'd do just what you said:
void f(void) {
void *p;
int ret;
...
ret = receive(&p);
}
What we don't know, given this much and the (justifiable) assumptions, are:
What does the ret value indicate?
Is p always valid afterward?
How many bytes at *p are accessible?
For instance, would:
struct our_data dst;
memcpy(&dst, p, len);
be a valid way to get the bytes from p into the data-structure dst, and if so, where does the length len come from? Is it implied, e.g., do we know that because ret was not -1 (error) that p is valid and has sizeof(struct our_data) bytes available, and we need the memcpy just to make it properly aligned?
If we knew all of these things, we'd be able to do the job directly from Go:
var p unsafe.Pointer
var obj C.struct_our_data
ret := C.receive(&p)
C.memcpy(unsafe.Pointer(&obj), p, len) // or similar with copy()
although it might—depending on task etc—make more sense to just write a deserializer for the raw data, which we obtain as an array living in C memory; see, e.g., How to convert [1024]C.char to [1024]byte.

Is it better to use pointer for non-primitive types in struct fields in Go

I am going on a project which process some data, I am wondering that if it is better to use pointer in non-primitive typed fields of struct.
What I've found is that the reason of using pointer is that nil can be used as a zero-value, is this the only reason to use pointer?
For example, I am going to store time.Time in my struct and it cannot be nil, then is it better to use non-pointer field?
So is it okay to use
type A struct {
CreatedAt time.Time
}
rather than
type A struct {
CreatedAt *time.Time
}
when Now is not going to be nil?
Not sure I understand the question. In the case of "Now" I would make it a function of the struct i.e.:
type A struct{}
func (a A) Now() time.Time { return time.Now(); }
otherwise what does Now mean? Now is constantly changing.
There are great blogs on when to use pointers
The short would be it doesn't really depend on if the value can be nil, but more on memory and concurrency. Pointers will be passed as references, so less memory, and faster, but also means that changing in one go routine can be very dangerous because the value could be referenced in another go routine and cause race conditions and unexpected behaviors.
I'm not really a professional or know the ins and outs of Go, so take everything I say with some grain of salt.
But as I am understanding it, you should most likely use pointers.
This is because every time you use a non-pointer type, the whole struct will be part of your struct in memory. As a consequence, you can't share a single instance of a struct between multiple structs - every single one gets a copy of your original struct.
Heres a small example:
// This struct has 2x64 bits in size
type MyStruct struct {
A uint64
B uint64
}
// This struct has 32 + 2x64 bits in size
type MyOtherStruct struct {
C uint32
Parent MyStruct
}
// This struct has 32 + the length of an address bits size
type MyPointerStruct struct {
D uint32
Parent *MyStruct
}
But apart from memory concerns, there is also a performance hit if your inner struct is very big. Because every time you set the inner struct the whole memory has to be copied to your instance.
However you have to be careful if your are dealing with interfaces or structs. At runtime, an interface is represented as a type with two fields: A reference to the actual (runtime) type and one with a reference to the actual instance.
So I - with my unprofessional opinion - would recommend to not use pointers if you have interface types because otherwise the CPU has to deference twice (once to get the interface reference, and then again to get the instance of the interface).

Can a struct in UPC have shared array as a field?

I need to store shared array inside a struct in UPC. Is it possible to do?
Struct fields cannot be shared-qualified, for the same reason they cannot be declared with static or extern - a struct field does not carry independent storage-class information (ie because the fields of a struct are always stored contiguously, and could be used for example to declare a stack variable).
However, a struct may contain an array field, and the struct can then be used to define a shared object, eg:
struct S {
int array[100];
int foo;
};
shared struct S data[THREADS];
...
data[MYTHREAD].array[0] = MYTHREAD;
However note the distribution of data in this example is one struct per thread, the array field is not independently distributed across threads.
A struct may also contain a pointer to a shared array, eg:
#include <upc.h>
struct R {
shared int *sa;
int bar;
};
...
struct R r;
r.sa = upc_all_alloc(THREADS, sizeof(int));
r.sa[MYTHREAD] = MYTHREAD;
in this case the shared array is distributed across threads, but the storage is not embedded in the struct - the struct field is just a pointer-to-shared (and thanks to C rules can be accessed with array syntax).

How can I fill out void* C pointer in Go?

I am trying to interface with some C code from Go. Using cgo, this has been relatively straight-forward until I hit this (fairly common) case: needing to pass a pointer to a structure that itself contains a pointer to some data. I cannot seem to figure out how to do this from Go without resorting to putting the creation of the structure into the C code itself, which I'd prefer not to do. Here is a snippet that illustrates the problem:
package main
// typedef struct {
// int size;
// void *data;
// } info;
//
// void test(info *infoPtr) {
// // Do something here...
// }
import "C"
import "unsafe"
func main() {
var data uint8 = 5
info := &C.info{size: C.int(unsafe.Sizeof(data)), data: unsafe.Pointer(&data)}
C.test(info)
}
While this compiles fine, trying to run it results in:
panic: runtime error: cgo argument has Go pointer to Go pointer
In my case, the data being passed to the C call doesn't persist past the call (i.e. the C code in question digs into the structure, copies what it needs, then returns).
See "Passing pointers" section in cgo docs:
Go code may pass a Go pointer to C provided the Go memory to which it points does not contain any Go pointers.
And also:
These rules are checked dynamically at runtime. The checking is controlled by the cgocheck setting of the GODEBUG environment variable. The default setting is GODEBUG=cgocheck=1, which implements reasonably cheap dynamic checks. These checks may be disabled entirely using GODEBUG=cgocheck=0. Complete checking of pointer handling, at some cost in run time, is available via GODEBUG=cgocheck=2.
If you run the snippet you've provided with:
GODEBUG=cgocheck=0 go run snippet.go
Then there is no panic. However, the correct way to go is to use C.malloc (or obtain a "C pointer" from somewhere else):
package main
// #include <stdlib.h>
// typedef struct {
// int size;
// void *data;
// } info;
//
// void test(info *infoPtr) {
// // Do something here...
// }
import "C"
import "unsafe"
func main() {
var data uint8 = 5
cdata := C.malloc(C.size_t(unsafe.Sizeof(data)))
*(*C.char)(cdata) = C.char(data)
defer C.free(cdata)
info := &C.info{size: C.int(unsafe.Sizeof(data)), data: cdata}
C.test(info)
}
It works because while regular Go pointers are not allowed, C.malloc returns a "C pointer":
Go pointer means a pointer to memory allocated by Go (such as by using the & operator or calling the predefined new function) and the term C pointer means a pointer to memory allocated by C (such as by a call to C.malloc). Whether a pointer is a Go pointer or a C pointer is a dynamic property determined by how the memory was allocated.
Note that you need to include stdlib.h to use C.free.

structure implementation for linked list

When I was reading about Linked list, I came to know that the structure for linked list as
Struct node{
Struct node *next;
int value;
}
Why is the Struct node *next? Why cant it just be an integer pointer? Like below
Struct node{
int *next;
int value;
}
why can't this hold the next node's address? Can anyone please give me explanation?
That's actually what a pointer (*next) does. It holds the address of something else. The type definition describes what this something else is (in this case struct node). Otherwise the application would not know how many bytes to read and how to interpret the data.
Read more about pointers.
Btw. int *next would hold the address of an integer.
Why is the Struct node *next? Why cant
it just be an integer pointer?
Because then you would be pointing to the address of the next integer. This could be used to retrieve the value of the next int, but nothing more, so from there on onward, you would be stuck.
By linking nodes together, which hold integer values, you can traverse the nodes and retrieve the int values.

Resources