When using malloc for a static pointer inside a function?

I don’t understand why the programmer used a static variable in the next code snippet (and, as a result, I began to doubt all my little knowledge):

int func (...) { static unsigned int *temp = NULL; if( temp == NULL ) { temp = malloc(dim*sizeof(*temp)); } // do stuff with temp } 

In main (), the func function is called several times in a loop:

 int main() { for (i = 0; i < N; ++i) x = func(...); } 

The first call to func initializes the temp variable to NULL, and thus temp is allocated (perhaps initialization is also redundant (according to this post).

The func function does nothing special with temp, just copy some values ​​into it from another (global) array if the condition is met and returns the number of written elements.

If I understand correctly, malloc allocates memory on the heap, so the memory will remain until it is explicitly freed, and since the pointer is static, they can be accessed in subsequent calls.

Then the questions are:

  • Do I understand this correctly?
  • What is the advantage of this approach instead of malloc temp outside func and then passing it func explicitly? I think it depends on the circumstances, well, but perhaps there is a well-known example. I also saw this answer , but I cannot understand the usefulness of the first example.
  • Should I free temp inside func (in the last step, which, by the way, is not executed in this code)?

I need to modify the above code (which is much more complicated), and I prefer to allocate temp outside of func and then pass it to a function, and I want to be sure that I am missing something important. By the way, I thought I could learn something :).

Thanks.

+5
source share
5 answers

"The first call to func initializes the temp variable to NULL ."

No, you are wrong (completely). A static variable is initialized by before . Any function (including) main called. This is why initializers for static variables must be constant expressions. As you correctly understood, without an explicit initializer, it will also be set to a null pointer during startup. It is doubtful if it is clearly better here. The problem with explicit initializers is that for real implementations, they consume additional space in the program store. For embedded systems with exposed metal coatings, this is expensive for storing Flash / ROM. Some compilers (like gcc) provide options for circumventing this fine.

So, the first call to func will effectively allocate an object that can then be used during subsequent calls. Note that the function (and its caller) must properly handle the placement failure.

The reason not to use a global variable is information hiding. In general, you should define variables in the smallest possible area (and reasonable). This way you can be sure that the variable will not be changed elsewhere. And the likelihood of a clash of names is minimized. Since C does not have custom namespaces, all such names are included in the global pool, which makes this problem very urgent.

free inclusion of such distributed data can be done in a variety of ways. One of them is to add a parameter to explicitly request free ing. In addition, there may be a global registry (basically a simple linked list) of such blocks. At the end of the program, the frame function will simply populate this list and free all blocks.

Alternatively, the program may simply rely on a runtime environment that automatically frees up dedicated storage upon exit. Although this is legal, this IMO is not the cleanest way.

+3
source
  • Do I understand this correctly?

You correctly understand temp initialization for all practical purposes and tasks, including that the explicit initializer is redundant. You also seem to understand the distribution correctly and mean temp declared by static . In practice, temp is probably initialized to NULL before func() ever called, and even if it is never called, but there is no way for the program to tell what the difference is from its initialization on the first call.

  1. What is the advantage of this approach instead of malloc temp outside func and then passing it func explicitly? I think it depends on the circumstances, well, but perhaps there is a well-known example. I also saw this answer, but I cannot understand the usefulness of the first example.

Presumably, the amount of storage required - as determined by the variable dim - is unknown until runtime. This is the reason for the dynamic distribution.

Placing a variable in the local area of ​​the function ensures that it has no connections - it is not visible and cannot be specified (directly) from anywhere outside the function. On the other hand, it is controlled by the function itself. Other functions need not worry about preparing an array for this function or passing one of them, and this function should not rely on anyone to properly configure the array.

As a stylistic question, I would be inclined to consider a static pointer to the file area (in the context of which, vaguely, the static means something else: internal communication, not static duration). The only difference would be the visibility of the variable.

Ultimately, however, the choice of visibility and the provision of a variable are design issues that have some solutions to some extent. You have not provided enough information for us to talk about specific options made in the code you are studying.

  1. Should I free temp inside func (in the last step, which, by the way, is not executed in this code)?

If temp freed, this should be done inside func() . One could set a copy of the temp pointer for code outside the function, in which case the allocated space could be freed using this pointer, but then temp would be left as an invalid pointer, without the possibility for func() to say.

However, the temp static creation point should certainly be stored in several function calls, so that the allocated space should not be freed and will not be skipped. Note, in particular, that since temp has a static duration, initialization to NULL is performed as if during program initialization, and not every time the function was called.

Actually, there is probably no need to free temp in this case. Doing this does not create a memory leak, because the memory allocated for temp still available unlimitedly (albeit within func() ). When the program exits, this memory will be returned to the operating system, like any other memory allocations still outstanding at that time.

+4
source

Do I understand this correctly?

Yes.

What is the advantage of this approach instead of malloc temp outside func and then passing it func explicitly?

In one case, each caller needs to know temp and its proper initialization for func , which makes subscribers strongly connected to func . If you need to change the type or size of the temp array at any time in the future, this will affect each caller. In another case, all this is abstracted.

Should I free temp inside func?

temp used throughout the entire program life cycle. If you free it at the end of a function, you will defeat its purpose, which is to reduce the number of calls to malloc and / or save data between calls. You can free it at the end of the program if you find a way. If you free it at the end of the function, you do not need it to be static, and you do not need the if (temp == NULL) test if (temp == NULL) . IOW you are losing the reason to ask this question.

+1
source
  • Do I understand this correctly?

Yes Yes.

  1. What is the advantage of this approach instead of malloc temp outside func and then passing it func explicitly? I think it depends on the circumstances, well, but perhaps there is a well-known example. I also saw this answer, but I cannot understand the usefulness of the first example.

The advantage is that function callers do not need to know that func needs a buffer to implement functions.

  1. should free temp inside func (in the last step, which, by the way, is not executed in this code)?

Yes you need. Unfortunately, how this is implemented, you cannot do this. No access to temp outside func . func not free because of how it was implemented.

For free memory allocated in func , you can use something along the lines of:

 static unsigned int *temp = NULL; void free_temp() { free(temp); } int func () { if( temp == NULL ) { temp = malloc(dim*sizeof(*temp)); // Register free_temp to be called at exit time. atexit(free_temp); } // do stuff with temp } 
+1
source
  • Yes.
  • Since we are in C, not C ++, I think this is a way to try to limit the ownership and management of allocated memory so as not to worry about it. Does it make sense to distribute this pointer outside of the one function that controls it?
  • Yes. If you are not going to cache this data or hold it until the program ends.
0
source

Source: https://habr.com/ru/post/1238969/


All Articles