We have this function prototype:
BNode *b_new_node(const char *name, int pos, int len, const char *val);
Most of the code using this(and similar) are autogenerated code, and looks like:
b = b_new_node("foo.bar.id.1", 0, 10, some_data);
The function allocates a new BNode and copies the val
string into it, but it just assigns the name
member to a pointer, e.g.
b_strlcpy(new_node->val, val, sizeof new_node->val);
new_node->name = name;
This wrecks havoc if the first argument in b_new_node("foo.bar.id.1", 0, 10, some_data); is not a string literal, or otherwise something with static storage duration, but e.g. a buffer on the stack.
Is there anyway, with gcc (other compilers are of interest too), we can have a compile time check that this argument is passed in is of static storage ?
(ofcourse the easy way to avoid these possible problems is to copy that argument too into the node - the measurements we did with that approach rises the memory need by 50% and slows the program down by 10%, so that approach is undesirable).
You can make
BNode
conditionally copy the name. That will require and extra bit of storage inBNode
. E.g.:This will detect string literals:
So you can wrap your b_new_node() function in a macro, perhaps just for a debug build, and harness the division by zero warnings.
Note that it only detects string literals as "arguments", not static storage, e.g.
Generally no; there is no C-provided facility to know whether or not a pointer points to something in static storage. Specific environments and data structures may change the circumstances - such as checking if the pointed-to address is in a read-only memory segment.
Saving space by countering duplication
To eliminate duplicated values, as pointed to by
name
, you could use the flyweight pattern which is not very different from string interning.Basically you build a central set of encountered tokens and store only the reference to each token. The references could be array indices or pointers.
To be able to clean-up quickly, you could combine the flyweight pattern with reference counting where a count of zero, means no references left.
To keep performance of the central store high, use a data structure where look-up is fast such as a set, or with a map if reference counting is used.