I was using a sample C ALSA program as reference and ran along the following piece of code:
...
snd_ctl_event_t *event;
snd_ctl_event_alloca(&event);
...
Based on the ALSA source code, snd_ctl_event_alloca is a macro that calls __snd_alloca which is a macro that finally expands to the following equivalent line for snd_ctl_event_alloca(&event); (with some straightforward simplification):
event = (snd_ctl_event_t *) alloca(snd_ctl_event_sizeof());
memset(event, 0, snd_ctl_event_sizeof());
where snd_ctl_event_sizeof() is only implemented once in the whole library as:
size_t snd_ctl_event_sizeof()
{
return sizeof(snd_ctl_event_t);
}
So my question is, isn't this whole process equivalent to simply doing:
snd_ctl_event_t event = {0};
For reference, these are the macros:
#define snd_ctl_event_alloca(ptr) __snd_alloca(ptr, snd_ctl_event)
#define __snd_alloca(ptr,type) do { *ptr = (type##_t *) alloca(type##_sizeof()); memset(*ptr, 0, type##_sizeof()); } while (0)
Clarifications:
The first block of code above is at the start of the body of a function and not in a nested block
EDIT
As it turns out (from what I understand), doing:
snd_ctl_event_t event;
gives a storage size of 'event' isn't known error because snd_ctl_event_t is apparently an opaque struct that's defined privately. Therefore the only option is dynamic allocation.
Since it is an opaque structure, the purpose of all these actions is apparently to implement an opaque data type while saving all the "pros" and defeating at least some of their "cons".
One prominent problem with opaque data types is that in standard C you are essentially forced to allocate them dynamically in an opaque library function. It is not possible to implicitly declare an opaque object locally. This negatively impacts efficiency and often forces the client to implement additional resource management (i.e. remember to release the object when it is no longer needed). Exposing the exact size of the opaque object (through a function in this case) and relying on alloca to allocate storage is as close as you can get to a more efficient and fairly care-free local declaration.
If function-wide lifetime is not required, alloca can be replaced with VLAs, but the authors probably didn't want/couldn't use VLAs. (I'd say that using VLA would take one even closer to emulating a true local declaration.)
Often in order to implement the same technique the opaque object size might be exposed as a compile-time constant in a header file. However, using a function has an added benefit of not having to recompile the entire project if the object size in this isolated library changes (as #R. noted in the comments).
Previous version of the answer (the points below still apply, but apparently are secondary):
It is not exactly equivalent, since alloca defies scope-based lifetime rules. Lifetime of alloca-ed memory extends to the end of the function, while lifetime of local object extends only to the end of the block. It could be a bad thing, it could be a good thing depending on how you use it.
In situations like
some_type *ptr;
if (some condition)
{
...
ptr = /* alloca one object */;
...
}
else
{
...
ptr = /* alloca another object */;
...
}
the difference in semantics can be crucial. Whether it is your case or not - I can't say from what you posted so far.
Another unrelated difference in semantics is that memset will zero-out all bytes of the object, while = { 0 } is not guaranteed to zero-out padding bytes (if any). It could be important if the object is then used with some binary-based API's (like sent to a compressed I/O stream).
Related
I need to create a library in C and I am wondering how to manage objects: returning allocated (ex: fopen, opendir) or in-place initialization (ex: GNU hcreate_r).
I understand that it is mostly a question of taste, and I'm inclined to choose the allocating API because of the convenience when doing lazy initialization (by testing if the object pointer is NULL).
However, after reading Ulrich's paper (PDF), I'm wondering if this design will cause locality of reference problems, especially if I compose objects from others:
struct opaque_composite {
struct objectx *member1;
struct objecty *member2;
struct objectz *member2;
/* ... */
};
Allocation of such an object will make a cascade of other sub-allocations. Is this a problem in practice? And are there other issues that I should be aware of?
The thing to consider is whether the type of the object the function constructs is opaque. An opaque type is only forward-declared in the header file and the only thing you can do with it is having a pointer to it and passing that pointer to separately compiled API functions. FILE in the standard library is such an opaque type. For an opaque type, you have no option but have to provide an allocation and a deallocation function as the user has no other way to obtain a reference to an object of that type.
If the type is not opaque – that is, the definition of the struct is in the header file – it is more versatile to have a function that does only initialization – and, if required, another that does finalization – but no allocation and deallocation. The reason is that with this interface, the user can decide whether to put the objects on the stack…
struct widget w;
widget_init(&w, 42, "lorem ipsum");
// use widget…
widget_fini(&w);
…or on the heap.
struct widget * wp = malloc(sizeof(struct widget));
if (wp == NULL)
exit(1); // or do whatever
widget_init(wp, 42, "lorem ipsum");
// use widget…
widget_fini(wp);
free(wp);
If you think that this is too much typing, you – or your users themselves – can easily provide convenience functions.
inline struct widget *
new_widget(const int n, const char *const s)
{
struct widget wp = malloc(sizeof(struct widget));
if (wp != NULL)
widget_init(wp, n, s);
return wp;
}
inline void
del_widget(struct widget * wp)
{
widget_fini(wp);
free(wp);
}
Going the other way round is not possible.
Interfaces should always provide the essential building blocks to compose higher-level abstractions but not make legitimate uses impossible by being overly restrictive.
Of course, this leaves us with the question when to make a type opaque. A good rule of thumb – that I have first seen in the coding standards for the Linux kernel – might be to make types opaque only if there are no data members your users could meaningfully access. I think this rule should be refined a little to take into account that non-opaque types allow for “member” functions to be provided as inline versions in the header files which might be desirable from a performance point of view. On the other hand, opaque types provide better encapsulation (especially since C has no way to restrict access to a struct's members). I would also lean towards an opaque type more easily if making it not opaque would force me to #include headers into the header file of my library because they provide definitions of the types used as members in my type. (I'm okay with #includeing <stdint.h> for uint32_t. I'm a little less easy about #includeing a large header such as <unistd.h> and I'd certainly try to avoid having to #include a header from a third-party library such as <curses.h>.)
IMO the "cascade of sub-allocations" is not a problem if you keep the object opaque so you can keep it in a consistent state. The creation and destruction routines will have some added complexity dealing with an allocation failure part way through creation, but nothing too onerous.
Besides the option to have a static/stack-allocated copy (which I'm generally not fond of anyway), in my mind, the main advantage of a scheme like:
x = initThang(thangPtr);
is the ease of returning a variety of more specific error codes.
What I want is to ensure that file scope variables (in my program) can not be modified from outside the file. So I declare them as 'static' to preclude external linkage. But I also want to make sure that this variable can not be modified via pointers.
I want something similar to the 'register' storage class, in that
the address of any part of an object declared with storage-class
specifier register cannot be computed, either explicitly (by use of
the unary & operator) or implicitly (by converting an array name to a
pointer).
but without the limitations of the 'register' keyword (can not be used on file scope variables, arrays declared as register can not be indexed).
That is,
<new-keyword> int array[SIZE] = {0};
int a = array[0]; /* should be valid */
int *p = array; /* should be INVALID */
p = &array[3]; /* should be INVALID */
What is the best way to go about achieving this goal?
Why do I desire such a feature?
The usage scenario is that this file will be modified by many people in the future even when I can not personally overview all modifications. I want to preclude as many potential bugs as possible. In this case I want to make sure that variables meant to be 'private' to the module will remain so without having to depend just on documentation and/or discipline
No, I don't think you can do so, at least not cleanly. But I also fail to understand your usage case fully.
If your object is static, nobody knows its name outside of your module. So nobody can use & to take its address.
If you need to expose it, and don't want other parts of the program modifying it, write a function that exposes it as a constant pointer:
static int array[SIZE];
const int * get_array(void)
{
return array;
}
Then compile with warnings. If somebody casts away the const, it's their problem.
Assuming you are concerned with security issues, here are a few things to consider:
The purpose of register keyword was to recommend the compiler to keep that variable in a register, as it will be intensively used. As the registers don't have a memory address, it is impossible to get it (although this wasn't the primary purpose of this keyword; it is merely a side-effect). As compilers got better at generating efficient code, this is not needed any more.
Even if you could make all objects in your code "addess-proof" (impossible to get their address), the program will still not be 100% safe. Those objects are still stored in memory, which is still visible. By analysing the binary files, using debuggers, analysing the memory map and so on, one could find out those memory addresses.
This is not a good practice. In order for someone to get the variable of an object in a module, that object must be global, which is bad. So you should worry about having global variables, not about their visibility. Here you can find more details about why is it bad to have variables in the global scope.
As a semi-solution to your "problem", you can declare them const static. This way they cannot be accessed from outside the module and if it happens, no one can change their value.
In C and C++ we can return structures or classes from functions and methods:
class A final { public:
int i;
A(int n) { this->i=n; }
};
A function(void) {
return A(4);
}
int main(void) {
A result = function();
return 0;
}
What I want to know is how is this implemented? The traditional wisdom is that it is copied, thus incurring a cost: to mitigate, you can pass a pointer to the structure instead and return nothing.
However, I'm not sure that this is (always) necessary. In the above, for example, the constructed structure was never used locally. Since we're returning it, couldn't the data be instead filled into the result variable one level higher directly, before the stack is popped?
The main problem to doing this, as I see it, is that the callee function needs to know where the caller wants the result. Another problem is in the case of more recursive functions: if the ultimate variable you're copying into is several layers higher in the stack, then it would become much harder for the callee to locate the correct place. My guess, based on my limited compiler knowledge, is that it is instead the caller that copies the struct from the callee, right after the return.
In general, I feel like such an optimization might be tricky. For inlined functions, I expect it to happen implicitly, and if the structure is never used locally, I can't see a reason why it couldn't be implemented this way. However, for everything else, I expect the issues you run into trying to implement it are too great, and indeed in general it is just copied.
So:
inline: (happens implicitly?)
return never-used new structure: (happens?)
recursive: (any complications?)
in general: (doesn't happen?)
In C++, compilers often use the copy elision idiom (often called " return value optimization") to avoid unnecessary copies when returning values. At least, they are often allowed to do it.
C++ Standard, section § 12.8 :
When certain criteria are met, an implementation is allowed to omit
the copy/move construction of a class object, even if the constructor
selected for the copy/move operation and/or the destructor for the
object have side effects. In such cases, the implementation treats the
source and target of the omitted copy/move operation as simply two
different ways of referring to the same object, and the destruction of
that object occurs at the later of the times when the two objects
would have been destroyed without the optimization.
This elision of copy/move operations, called copy elision, is
permitted in the following circumstances (which may be combined to
eliminate multiple copies)
In a return statement in a function with a class return type, when the
expression is the name of a non-volatile automatic object (other than
a function or catch-clause parameter) with the same cv- unqualified
type as the function return type, the copy/move operation can be
omitted by constructing the automatic object directly into the
function’s return value
...
C89
gcc (GCC) 4.7.2
Hello,
I am maintaining someones software and I found this function that returns the address of a static structure. This should be ok as the static would indicate that it is a global so the address of the structure will be available until the program terminates.
DRIVER_API(driver_t*) driver_instance_get(void)
{
static struct tag_driver driver = {
/* Elements initialized here */
};
return &driver;
}
Used like this:
driver_t *driver = NULL;
driver = driver_instance_get();
The driver variable is used throughout the program until it terminates.
some questions:
Is it good practice to do like this?
Is there any difference to declaring it static outside the function at file level?
Why not pass it a memory pool into the function and allocate memory to the structure so that the structure is declared on the heap?
Many thanks for any suggestions,
Generally, no. It makes the function non-reentrable. It can be used with restraint in situations when the code author really knows what they are doing.
Declaring it outside would pollute the file-level namespace with the struct object's name. Since direct access to the the object is not needed anywhere else, it makes more sense to declare it inside the function. There's no other difference.
Allocate on the heap? Performance would suffer. Memory fragmentation would occur. And the caller will be burdened with the task of explicitly freeing the memory. Forcing the user to use dynamic memory when it can be avoided is generally not a good practice.
A better idea for a reentrable implementation would be to pass a pointer to the destination struct from the outside. That way the caller has the full freedom of allocating the recipient memory in any way they see fit.
Of course, what you see here can simply be a C implementation of a singleton-like idiom (and most likely it is, judging by the function's name). This means that the function is supposed to return the same pointer every time, i.e. all callers are supposed to see and share the same struct object through the returned pointer. And, possibly, thy might even expect to modify the same object (assuming no concurrency). In that case what you see here is a function-wrapped implementation of a global variable. So, changing anything here in that case would actually defeat the purpose.
As long as you realize that any code that modifies the pointer returned by the function is modifying the same variable as any other code that got the same pointer is referring to, it isn't a huge problem. That 'as long as' can be a fairly important issue, but it works. It usually isn't the best practice — for example, the C functions such as asctime() that return a pointer to a single static variable are not as easy to use as those that put their result into a user-provided variable — especially in threaded code (the function is not reentrant). However, in this context, it looks like you're achieving a Singleton Pattern; you probably only want one copy of 'the driver', so it looks reasonable to me — but we'd need a lot more information about the use cases before pontificating 'this is diabolically wrong'.
There's not really much difference between a function static and a file static variable here. The difference is in the implementation code (a file static variable can be accessed by any code in the file; the function static variable can only be accessed in the one function) and not in the consumer code.
'Memory pool' is not a standard C concept. It would probably be better, in general, to pass in the structure to be initialized by the called function, but it depends on context. As it stands, for the purpose for which it appears to be designed, it is OK.
NB: The code would be better written as:
driver_t *driver = driver_instance_get();
The optimizer will probably optimize the code to that anyway, but there's no point in assigning NULL and then reassigning immediately.
I am studying on "reading code" by reading pieces of NetBSD source code.
(for whoever is interested, it's < Code Reading: The Open Source Perspective > I'm reading)
And I found this function:
/* convert IP address to a string, but not into a single buffer
*/
char *
naddr_ntoa(naddr a)
{
#define NUM_BUFS 4
static int bufno;
static struct {
char str[16]; /* xxx.xxx.xxx.xxx\0 */
} bufs[NUM_BUFS];
char *s;
struct in_addr addr;
addr.s_addr = a;
strlcpy(bufs[bufno].str, inet_ntoa(addr), sizeof(bufs[bufno].str));
s = bufs[bufno].str;
bufno = (bufno+1) % NUM_BUFS;
return s;
#undef NUM_BUFS
}
It introduces 4 different temporary buffers to wrap inet_ntoa function since inet_ntoa is not re-entrant.
But seems to me this naddr_ntoa function is also not re-entrant:
the static bufno variable can be manipulated by other so the temporary buffers do not seem work as expected here.
So is it a potential bug?
Yes, this is a potential bug. If you want a similar function that most likely reentrant you could use e.g. inet_ntop (which incidentally handles IPv6 as well).
That code comes from src/sbin/routed/trace.c and it is not a general library routine, but just a custom hack used only in the routed program. The addrname() function in the same file makes use of the same trick, for the same reason. It's not even NetBSD code per se, but rather it comes from SGI originally, and is maintained by Vernon Schryver (see The Routed Page).
It's just a quick hack to allow use of multiple calls within the same expression, such as where the results are being used in one printf() call: E.g.:
printf("addr1->%s, addr2->%s, addr3->%s, addr4->%s\n",
naddr_ntoa(addr1), naddr_ntoa(addr2), naddr_ntoa(addr3), naddr_ntoa(addr4));
There are several examples of similar uses in the routed source files (if.c, input.c, rdisc.c).
There is no bug in this code. The routed program is not multi-threaded. Reentrancy is not being addressed at all in this hack. This trick has been done by design for a very specific purpose that has nothing to do with reentrancy. The Code Reading author(s) is wrong to associate this trick with reentrancy.
It's simply a way to hide the saving of multiple results in an array of static variables instead of having to individually copy those results from one static variable into separate storage in the calling function when multiple results are required for a single expression.
Remember that static variables have all the properties of global variables except for the limited scope of their identifier. It is of course true that unprotected use of global (or static) variables inside a function make that function non-reentrant, but that's not the only problem global variables cause. Use of a fully-reentrant function would not be appropriate in routed because it would actually make the code more complex than necessary, whereas this hack keeps the calling code clean and simple. It would though have been better for the hack to be properly documented such that future maintainers would more easily spot when NUM_BUFS has to be adjusted.