Send parameters to alloc_cb - libuv

I want to use libuv to send files over TCP.
My problem is with uv_read_start for reading the content of the file.
To do that, I first send the size of the file, so I make a static malloc(sizeof(uint64_t)) in the alloc_cb to read the size.
After that I have to make malloc(size) to allocate the necessary amount of memory to fill all the file in memory (I absolutely want to have the file like this in memory).
But I don't know how to pass the argument size to the alloc_cb (I don't want to use global variable).
Is there a way to do that without global variable?
Perhaps a way totaly different to do the same thing?
Thanks in advance.

I see that handle->data contain a void* so we can put in exactly what we want.
Before calling uv_read_start store the size in the stream handle stream->data = (size_t*)malloc(sizeof(size_t)); and *(size_t *)(stream->data) = size;, and reuse it in alloc_cb by reading size_t rsize = *(size_t*)(handle->data);.
After that you must free this buffer.
Any other ideas?

As OP mentioned, using the void * field is an option.
The other is to use inheritance (if using C++) or inheritance-style hackery in C.
For C++ : we use inheritance.
struct my_struct: public uv_handle_t {
size_t size;
};
You can pass a pointer to this structure to alloc_cb (since my_struct inherits from handle), and then cast it back to type my_struct:
my_struct * s = reinterpret_cast<my_struct*>(handle);
For C : we don't have inheritance, so we need a bit of a hack:
struct my_struct {
uv_handle_t handle;
size_t size;
};
Then call alloc_cb after casting a pointer to an object of type my_struct to uv_handle_t ((uv_handle_t*) s), and cast back to my_struct inside alloc_cb:
my_struct * s = (my_struct*) handle;
The C method is explained in more details (though in a different context) in the book An introduction to libuv, release 2, at paragraph 8.4 "Passing data to worker thread" (see here).

Related

Difference between initializations of struct elements

I'm creating some functions that work with a struct that simulates an ethernet header.
typedef struct ethernet_hdr_ {
dir_mac_t dst_mac;
dir_mac_t src_mac;
short type;
char payload[MAX_SIZE_PAYLOAD];
unsigned int FCS;
} ethernet_hdr_t;
#define ETH_HDR_SIZE_EXCL_PAYLOAD (sizeof(ethernet_hdr_t) - sizeof(((ethernet_hdr_t *)0)->payload))
I need to define the next function.
static inline ethernet_hdr_t * ALLOC_ETH_HDR_WITH_PAYLOAD(char *pkt, unsigned int pkt_size)
According to this assignment, which I already did, but I want to know whether there is something wrong with my solution.
The above API must encapsulate the existing DATA into the payload of
ethernet header, i.e. above API must return a pointer to the ethernet
hdr the payload of which carries the data of size pkt_size pointed by
pkt in above diagram.
The layout of data with new ethernet hdr must look like given in the
image Q3 attached in the instruction of this assignment. Initialize
all the fields of the new ethernet hdr (including FCS) exclusing
payload to zero.
This is Q3.
This is how I did it.
static inline ethernet_hdr_t * ALLOC_ETH_HDR_WITH_PAYLOAD(char *pkt, unsigned int pkt_size) {
ethernet_hdr_t *ethernet_hdr = calloc(1, sizeof(ethernet_hdr_t));
memcpy(ethernet_hdr->payload, pkt, pkt_size);
return ethernet_hdr;
}
However, I found the official solution to this assignment, and it is very different from mine.
static inline ethernet_hdr_t * ALLOC_ETH_HDR_WITH_PAYLOAD(char *pkt, unsigned int pkt_size) {
char *temp = calloc(1, pkt_size);
memcpy(temp, pkt, pkt_size);
ethernet_hdr_t *eth_hdr = (ethernet_hdr_t *)(pkt - ETH_HDR_SIZE_EXCL_PAYLOAD);
memset((char *)eth_hdr, 0, ETH_HDR_SIZE_EXCL_PAYLOAD);
memcpy(eth_hdr->payload, temp, pkt_size);
free(temp);
return eth_hdr;
}
Clearly, my function is much simpler but I think it is missing something. So, I'm wondering whether both solutions are correct, but even if they are, maybe the second one is better.
In your case you are creating a new object to store the packet header and payload (frame) data, setting the header to zeros and copying the payload from pkt to the new frame data object payload member.
In the "official" solution, the program assumes that pkt points to the payload member of an object of type ethernet_hdr_t. Then, in a very complicated fashion, it attempts to do the same thing as your code, but using the original object of which pkt is a member.
Overall, I would say that the "official" solution is the problematic for several reasons:
It assumes that the compiler will arrange the contents of struct ethernet_hdr_ in a specific way, but this is actually defined by the implementation. This is due to the macro ETH_HDR_SIZE_EXCL_PAYLOAD using the object and member payload sizes to attempt to locate payload within the struct. A safer way might be to use the standard library offsetof macro to determine the offset of member payload within the struct.
Assuming that pkt is a member of another object type is not a good programming practice. For example, assume that the payload contents were copied to another object, which is not a member of ethernet_hdr_t prior to calling ALLOC_ETH_HDR_WITH_PAYLOAD. This would result in a memory access violation. The function should only attempt to access the objects provided as parameters and not objects that these objects "may" be members of.
The use of temp in this function does not make much sense. The payload data is effectively copied to temp then copied back to pkt indirectly through the object pointed to by eth_hdr.
The object generating the inputs to ALLOC_ETH_HDR_WITH_PAYLOAD is being updated by the function and the returned pointer will point to the same object. This could lead to some confusion by anyone trying to use the function.
In the case of your code, it accomplishes the same thing as the "official" answer, but creates a new object to contain the data. You will need to be sure that the memory is properly deallocated once the object is no longer needed, but when comparing the two, I would argue that your code is more correct in that it will not result in undefined, implementation-defined or confusing behavior.

Can I treat size_t as a void pointer?

I am working with an external library that is storing void* inside of a queue. For example,
void queue_insert(Queue* queue, void* data);
However, I want to store size_t data inside the queue instead. I can't pass the address of the size_t data (because it's locally scoped). I never need to access the data again, though.
In other words, I will be calling these functions
queue_insert(queue, 5);
bool exists = queue_contains(queue, 5);
but I will never be doing the following (because it doesn't make sense)
void* p = queue_pop(queue);
size_t s = *p;
With that being said, can I pass size_t variables to a function that takes a void*?
Typically, when a general-purpose library offers algorithms such as queue management, sorting, spawning threads, and so on, a void * parameters essentially means “I will take a handle to anything you want. Just put it in memory and give me a pointer to it. I will give you the pointer back when you need it.”
This is often used with a structure. Need to manage job information passed to a thread, like starting and ending indices, configuration parameters, and more? Define a structure type, allocate memory for it, pass the address of the memory for the library’s void * parameter. But it can also be used with a scalar item too.
To pass a size_t, use malloc to allocate space for the size_t, put the value in the allocated space, and pass the address to queue_insert.
When you are popping an element, use size_t *s = queue_pop(queue);. Then *s is the size_t you stored. When you are doing with it, free the memory with free(s).

is there a qualifier to indicate a C pointer as 'given to you and should be freed by you'?

I am writing a C project and need implement some functions, for some of them I need to return a pointer and rely on the caller to free() it, and for some I just lend the pointer to him.
Is there a qualifier in C preceeding the pointer to show the convention, like:
you_free_it char *foo();
just_lend_you char *foo2();
And when I am a caller, I also want to qualify my pointer variable which receives the result for safer operation. like:
you_free_it char *ptr = foo();
just_lend_you char *ptr2 = foo2();
You can actually return a struct:
struct resourceptr {
void *p;
};
char *dont_free_me();
struct resourceptr free_me();
struct resourceptr will be exactly as big as a pointer, but it's very clear that it's different from a normal pointer. (void * will implicitly convert to anything though...)
A few points:
If you have an interface which returns an allocated resource, provide a function to free that resource. In this example, don't ask the caller to call free(), provide a specific function that they have to call, which will call free(). Otherwise you're leaking implementation details through your abstraction.
Your question is also tagged with "C++". If you're in C++, then:
Use new and delete not malloc() and free().
You can just return an rvalue reference to an std::string, IIRC.
There are ways to implement classes that are reference-counted, does not incur extra memory allocations, and implicitly convert to char * and/or std::string.
Like #doug said, there's unique_ptr - that incurs another memory allocation though, in case you care about that.
I completely agree with the comments, there is no "canonical" way to do this in C. But if you need to communicate ownership of a resource explicitly (i.e. not just though documentation which explains to users of your library which resources must be free'd), I would suggest one possible approach:
#include <stdlib.h>
#define USER_MUST_FREE(res) ( (res->type) == USER_FREE ? 1 : 0 )
enum RES_TYPE { API_FREE, USER_FREE }; /* type of resource */
struct res_ptr {
enum RES_TYPE type;
void *ptr; /* the actual resources, could be any type */
/* could hold a function pointer to a custom `free' function */
};
typedef union {
enum RES_TYPE type;
struct res_ptr *res;
/* could hold other types of resources, too */
} my_resource;
int main(void)
{
my_resource *resource;
resource = some_resource_generator(); /* function omitted for simplicity */
/* do something with the resource */
if (USER_MUST_FREE(resource)) {
free(resource->res->ptr);
free(resource->res);
free(resource);
}
return 0;
}
In this example, a union my_resource holds information about whether a resource should be free'd by the user or if freeing is handled by the library's API automatically. In a larger-scale application, one could push all resources on a dedicated stack and when cleaning up, loop over that stack, asking every resources if it needs to be deallocated. I used this pattern before and with some utility functions/a nicer API it worked well for me!

safely resizing structs

I would like some advice on safe ways to deal with struct's when the size of certain members are not known at code time.
For example I have a Struct Named "Channel". This struct has a member name "AudioSourceOBJ" which is a pointer to an an array of other struct type named "AudioSource". I wont know how many AudioSources I will have per channel until the program is run. I deal with that like this.
channel object
struct channelobj {
AudioUnitSampleType *leftoutput;
AudioUnitSampleType *rightoutput;
AudioSourceOBJ *audioSource;
};
audiosource
struct audiosourceobj {
AudioUnitSampleType *leftoutput;
AudioUnitSampleType *rightoutput;
};
creation of variable sized structs
void createInputs(ChannelOBJ channel,int numAudioInputs)
{
channel->audioSource=(AudioSourceOBJ *)malloc(numAudioInputs * sizeof(AudioSourceOBJ));
for (int i=0;i<numAudioInputs;i++)
{
AudioSourceOBJ obj;
obj=newAudioSourceOBJ();
channel->audioSource[i]=obj;
}
}
I think this is o.k?
The problem I am now facing is that even though I can assign memory for the correct number of audio objects in my channel struct, the leftoutput and rightoutput arrays in the audiosource struct will not be set until later in the program. They will be filled with an undermined amount of data, and are likely to change in size and content throughout the lifetime of the application.
Will I have to completely re malloc the channel containing the audiosource every time I want to make changes to a single audio object?
What is a safe way to do this or is there a better approach?
"Will I have to completely re malloc the channel containing the audiosource every time I want to make changes to a single audio object?"
No. You could for example replace the left output of the ith audio source like this:
free(channel->audioSource[i].leftoutput);
channel->audioSource[i].leftoutput = malloc(newSize * sizeof(AudioUnitSampleType));
Or even:
AudioUnitSampleType *tmp = realloc(channel->audioSource[i].leftoutput,
newSize * sizeof(*tmp));
if (tmp == 0) { /* handle the error */ }
channel->audioSource[i].leftoutput = tmp;
By the way, if you don't post real code, it's possible that answers will contain errors due to errors in your examples.
There seems to be some confusion in your code between pointers and objects, for example the channel parameter is of type ChannelOBJ, then you use it as if it's a pointer. Is this an error, or is ChannelOBJ a typedef for struct channelobj*? It's generally better not to conceal that something is a pointer using a typedef.
If AudioUnitSampleType is likewise a pointer type, then my first code snippet above is incomplete, since it would then also be necessary to free the old objects pointed to by the elements of the array, and allocate new ones. The second one needs to free old ones or allocate new ones according to whether the size is being increased or decreased.
No, you won't have to resize the allocated block of AudioSourceObj structs. leftoutput and rightoutput are merely pointers of a fixed size (not variable-sized arrays) and can be assigned an address by doing a separate malloc:
channel->audioSource[i].leftoutput = malloc(5 * sizeof(AudioUnitSampleType));

Struct with array member in C

Recently I reviewed some C code and found something equivalent to the following:
struct foo {
int some_innocent_variables;
double some_big_array[VERY_LARGE_NUMBER];
}
Being almost, but not quite, almost entirely a newbie in C, am I right in thinking that this struct is awfully inefficient in its use of space because of the array member? What happens when this struct gets passed as an argument to a function? Is it copied in its entirety on the stack, including the full array?
Would it be better in most cases to have a double *some_pointer instead?
If you pass by value yes it will make a copy of everything.
But that's why pointers exist.
//Just the address is passed
void doSomething(struct foo *myFoo)
{
}
Being passed as an argument it will be copied which is very inefficient way of passing structures, especially big ones. However, basically, structs are passed to functions by pointer.
Choosing between
double some_big_array[VERY_LARGE_NUMBER];
and
double *some_pointer
depends only on the program design and how this field/structure will be used. The latter allows using variable size storage, however may need dynamic allocation.
There are plenty of reasons to use arrays in structs. Among them is the fact that structs are passed to functions by value, while arrays are passed by reference. That said, this struct is probably passed to functions with pointers.
As others have said, objects of that type are usually passed around with pointers (always sizeof (struct foo) bytes, often 4 bytes).
You may also see the "struct hack" (also passed around with pointers):
struct foo {
int some_innocent_variables;
double some_array[]; /* C99 flexible array member */
/* double some_array[1]; ** the real C89 "struck hack" */
}
This "struct hack" gets an array sized by the malloc call.
/* allocate an object of struct foo type with an array with 42 elements */
struct foo *myfoo = malloc(sizeof *myfoo + 42 * sizeof *myfoo->some_array);
/* some memory may be wasted when using C89 and
the "struct hack" and this allocation method */
Yes, in C you would usually pass a pointer to the structure around due to efficiency reasons.
That structure is fine as long as you pass it by reference (using a pointer).
Offtopic:
Beware of the struct hack, as it is not strictly standard compliant; it ignores the automatic padding. The Unix IPC messaging queues use it (see struct msgbuf), though, and it is almost certainly to work with any compiler.
That said, the functions that use that structure may use pointers to it instead of using a copy.

Resources