Providing Static Storage for a Function Parameter

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) code is auto-generated code and looks like this:

  b = b_new_node("foo.bar.id.1", 0, 10, some_data); 

The function selects a new BNode and copies the string val into it, but it just assigns the member name pointer, for example.

  b_strlcpy(new_node->val, val, sizeof new_node->val); new_node->name = name; 

This destroys chaos if the first argument is in b_new_node ("foo.bar.id.1", 0, 10, some_data); is not a string literal or otherwise with a static storage duration, but, for example, a buffer on the stack.

In any case, with gcc (other compilers are also interesting), can we check the compilation time so that this argument is passed to static storage?

(of course, an easy way to avoid these possible problems is to copy this argument also to node - the measurements we made with this approach increase the memory requirement by 50% and slow down the program by 10%, so the approach is undesirable).

+4
source share
3 answers

This will detect string literals:

 #include <stdio.h> #define PRINT_IT(c) do {\ if (__builtin_constant_p(c))\ print_it(c, 1);\ else \ 1/__builtin_constant_p(c);\ } while (0) void print_it(const char *c, int is_static) { printf("%s is a constant %d\n", c, is_static); } int main(int argc, char *argv[]) { char bar[] = "bar"; PRINT_IT("Foo"); //line 19 PRINT_IT(bar); //line 20 return 0; } $ gcc foo.c foo.c: In function 'main': foo.c:20: warning: division by zero 

So, you can wrap your b_new_node () function in a macro, perhaps only to build debugging and use division by zero warnings.

Note that it only defines string literals as "arguments" and not static repositories, for example

 const char *foo = "foo"; PRINT_IT(foo); //will generate a warning PRINT_IT("foo"); //will not generate a warning PRINT_IT(global_foo); //will generate a warning, even when. //global_foo is const char *foo = "foo"; or //global_foo is const char foo[] = "foo"; 
+1
source

Generally not; There is no C-provisioning facility to find out if a pointer points to something in static storage. Specific environments and data structures can change circumstances - for example, to check whether a specified address is in a read-only segment.

Preserving space by counteracting duplication

To eliminate duplicate values, as indicated by name , you can use a template fly that is not much different from the intern string .

Basically, you create a central set of met tokens and save only a link to each token. Links can be indexes or pointers to an array.

To quickly clean up, you can combine a fly template with a reference count , where a zero count means no links are left.

To maintain high performance of the central repository, use a data structure in which a quick search, such as a set, or using map if reference counting is used.

+1
source

You can make BNode conditionally copy the name. This will require an additional bit of memory in the BNode . For instance:.

 typedef struct BNode { char const* name; unsigned char : own_name; } BNode; void b_copy_name(BNode* n) { if(!n->own_name) { char* p = strdup(n->name); if(p) { n->own_name = 1; n->name = p; } else { abort(); } } } void b_destroy(BNode* n) { // ... if(n->own_name) free(n->name); } 
0
source

All Articles