I am working on microntroller RZA1, with KPIT GNUARM 16 toolchain, in e2 studio. I am not an expert on the subject, so I'll try to explain the problem the best that I can. The issue is related to a structure mainwindow, defined in my code, which contains important features of the graphical interface:
typedef struct
{
page_t pages[MAXNUMPAGE];
logger_t storico;
messagges_t messaggio;
graph_t grafico;
} mainwindow_t;
In the main() function I declare a local instance of this struct, as it contains a while(1) loop, which is used to refresh the GUI application in case of user interaction (i.e pushbutton clicked). The problem that I have encountered is that there's a difference in the way program executes in case the instance of mainwindow_t is declared with or without static keyword. For instance,
main()
{
static mainwindow_t mainwindow;
....
init_pages(mainwindow.pages);
while(1)
{
page_update(mainwindow.pages);
}
}
works perfectly well, whereas with only mainwindow_t mainwindow; it seems that the changes made in the function init_pages() had no effect: entire content of the array page[MAXNUMPAGE] is uninitialized.
Therefore, my question is: should there be any functional difference between non-static local and static local declaration of an array inside a function, if that function basically never returns ?
The problem has nothing to do with whether the variable lives on the stack or not. It has to do with initialization.
Variables with static storage duration, i.e. file-scope variables or local variables with the static keyword, are implicitly initialized so that (loosely speaking) all variables with arithmetic type are initialized to 0 and all pointer variables are initialized to NULL.
In contrast, variables with automatic storage duration, i.e. variables declared inside of a function, are not initialized if there is no explicit initializer and its value is indeterminate.
While you didn't show your initialization function, it apparently doesn't set all fields in mainwindow.pages and depends on the other fields being zero-initialized. When mainwindow is declared non-static, this results in your program reading some indeterminate fields which causes undefined behavior, which explains why the problem mysteriously disappears when you attempt to trim down the code.
Adding an initializer to mainwindow addresses this issue by setting any fields explicitly listed, while applying the static object initialization rules to any remaining fields not explicitly initialized.
Related
So my question is: the "Title" and what are the garbage collection rules for dynamic arrays in SystemVerilog?
Context:
In my program, I found a bug where you can instantiate a dynamic array in a function (locally) and add elements to that array within that function, but if you don't delete the array, the entries remain there (i.e. memory and reference is preserved). So when you call the function again, all the entries that were previously entered can be accessed. The solution is to simply delete the dynamic array before you exit the function. I am assuming the array isn't deleted because the array is instantiated on the Heap instead of the Stack, and the compiler doesn't know when to garbage collect it because it could be a returned reference (please correct me if I am wrong - I am not familiar with the garbage collection rules for dynamic arrays).
However, what happens if the dynamic array is instantiated within a class (as a member variable)? How do you know if the dynamic array is deleted (i.e. reference and memory is removed)? What are the garbage collection rules for that case?
I have example code to demonstrate the issue if it is helpful but I don't think it is necessary to include it (let me know if you'd like an example).
P.S. The same thing happens for associative-arrays as well (because I think it is a form of dynamic array type in SystemVerilog).
Thanks!
SystemVerilog has three different kinds of variable lifetimes:
static -- exists for the entire life of the simulation. Initilized once at time 0. Can be referenced from outside the scope of where it's declared
automatic -- a new instance gets created and initialized for each entry to the scope where it is declared (must be a procedural scope). Its lifetime ends when exiting the scope, and all nested scopes exit (to handle fork/join_none) Can only be referenced from within the scope where it is declared
dynamic -- created by the execution of a procedural statement. It's lifetime can end a number of ways, but normally by executing a procedural statement.
Dynamically sized arrays have a compound concept of lifetimes. Individual elements have dynamic lifetimes, but the array as a whole aggregate can have any of the above lifetimes. For the purposes of your question, I think we can just consider the array as an aggregate. That means whenever the lifetime of an array variable ends, all the dynamically allocated elements are reclaimed
Class objects have dynamic lifetimes, but the class variables that hold handles referencing class objects can any of the above lifetimes. But since more than one class variable can reference the same class object, the lifetime of class object ends when there are no more class variables referencing that object. So if that class object contains dynamic array variables, those variables lifetime end when the objects lifetime ends.
SystemVerilog doesn't specify how garbage collection works. When the lifetime of something ends, you can no longer access it. There is no way to know when the memory actually gets reclaimed.
Your problem seems like you have a statically declared dynamic array inside a function, or a static function argument. In Verilog, all non-class functions have static lifetimes by default. Class methods can only have automatic lifetimes. If this explanation does not answer your question, you'll need to post some code.
BTW, this became the subject of my DVCon 2021 Paper and Presentation
GCC and Clang do compile the following code:
void Test()
{
constexpr int Size = 3;
auto Lambda = [Size]{ int Dim[Size]; };
}
However, VisualStudio 2015 CTP 6 does not. Nevertheless, all 3 compilers are happy with this code:
void Test()
{
static constexpr int Size = 3;
auto Lambda = []{ int Dim[Size]; };
}
Which snippet is actually doing it in the correct way? What does the C++ standard say?
This question is related to Lambda capturing constexpr object
C++11 [expr.prim.lambda]/12
If a lambda-expression odr-uses this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression.
and /17
Every id-expression that is an odr-use of an entity captured by copy is transformed into an access to the corresponding unnamed data member of the closure type. [ Note: An id-expression that is not an odr-use
refers to the original entity, never to a member of the closure type. [...]
— end note ]
So we don't even need to capture Size in the first example (where it is not static), since reading from that variable is not an odr-use since it can appear in a constant expression and the lvalue-to-rvalue conversion is immediately applied to it, [basic.def.odr]/2
A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression and the lvalue-to-rvalue
conversion is immediately applied.
(It is not clear to me if the array bounds require an l-t-r conversion, though.)
The same applies when capturing Size by reference, or when capturing Size explicitly (by copy) but not odr-using it: the use of the id-expression Size within the lambda accesses the constexpr variable declared in Test, not any captured member (for capture-by-copy: IFF the access does not constitute an odr-use).
C++14 [expr.prim.lamda]/12 adds some wording for polymorphic lambdas that is irrelevant here, and moves /17 to /18. The rules for odr-use are more complicated, but I'd argue it's not an odr-use for the same underlying reason (reading a compile-time constant).
I'm trying to understand this function and convert it to ctypes:
15 XDisplay* GetXDisplay() {
16 static XDisplay* display = NULL;
17 if (!display)
18 display = OpenNewXDisplay();
19 return display;
20 }
We see here if(!display) then do display = OpenNewXDisplay(); but what confuses me is the guy defines on the line above it that display is NULL (static XDisplay* display = NULL;) so why on earth the need for the if, if he just set it to null? Is display a global variable somehow?
display is a static variable.
For a static variable, initialisation only happens once, not every time the function is entered. This is just basic C (also basic C++, or basic Objective-C).
So this code is just a primitive way to create a singleton object.
As the others mentioned before display is a static variable.
The static storage class instructs the compiler to keep a local
variable in existence during the life-time of the program instead of
creating and destroying it each time it comes into and goes out of
scope. Therefore, making local variables static allows them to
maintain their values between function calls.
Source: http://www.tutorialspoint.com/cprogramming/c_storage_classes.htm
You should read more about whats static word means:
http://en.wikipedia.org/wiki/Static_variable
basicly it means that the variable will be defined only once. which means that on the next time the function will be called the previous value of the variable will be stay.
So its not quite a global variable since its has the scope of a regular variable but keeps its value over function calls.
I have written a Simulink S-function (Level 2) in C. The resulting block has one output and one parameter. This parameter is stored in a variable, which is defined at file scope, right after setting up the block:
#define NUM_PARAMS 1
#define NUM_INPORTS 0
#define NUM_OUTPORTS 1
unsigned short int MASK_INDEX;
I assign it within mdlInitializeSizes, and do some operations on its value:
static void mdlInitializeSizes(SimStruct *S) {
// Check Parameters
ssSetNumSFcnParams(S, NUM_PARAMS);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}
MASK_INDEX = *mxGetPr(ssGetSFcnParam(S, 0));
(...) operations
}
My problem is, that the variable MASK_INDEX seems to be global, and shared among all blocks of the same type. Therefore, it holds the same value for all blocks.
As a workaround, I reload it every time, and re-do the operations, for example:
static void mdlOutputs(SimStruct *S, int_T tid) {
MASK_INDEX = *mxGetPr(ssGetSFcnParam(S, 0));
(...) operations
}
How can I get a true "local variable", so that I don't have to repeat all this every time?
You haven't mentioned where you've declared MASK_INDEX, but from your description it sounds like it's at file scope. If so, then yes, this variable will be shared across all instances. This is not isolated to S-Functions in any way, it's how shared libraries on most, if not all, platforms behave. A single instance of the shared library will be loaded by an application, in this case MATLAB; consequently there is only one copy of global variables.
The easiest option is to use ssGetSFcnParam every time you want to access the parameter. If you dig into those S-Function macros, they're simply accessing fields of the SimStruct, so it's unlikely repeated access will result in performance degradation. I've even seen macros being used to wrap common use cases such as the one you have.
If you really want to go about caching the dialog parameter, the easiest is probably to use ssSetUserData. Declare a struct containing a MASK_INDEX member (you don't have to use a struct but this approach is more extensible). Dynamically allocate an instance using mxMalloc within mdlStart and assign it to the block's user data. Make sure you set SS_OPTION_CALL_TERMINATE_ON_EXIT in the ssSetOptions call in mdlInitializeSizes. Then define the mdlTerminate function within which you'll access the allocated struct using ssGetUserData and mxFree it. Now you can access the struct members within mdlOutputs using ssGetUserData.
There are other, more advanced options as well, such as work vectors, probably a PWork vector.
Another option, if your parameter is tunable, is using runtime parameters, which let you cache, and optionally transform, a block's dialog parameters.
In your case, I'd just stick with using ssGetSFcnParam every time within mdlOutputs.
I came across this piece of C code:
main(){
static int i=0;
i++;
if(i<=5){
int i = 3;
printf(" %d",i);
main();
}
}
1. First, I expected this code to give a compilation error as there are multiple definitions of the variable i. But, it compiled and ran successfully and gave this output.
3 3 3 3 3
2. Observing the output, 3 is printed exactly 5 times, which means the loop was counted from 0 to 5 thus implying that for the if condition , the first definition (static) of i was used.
3 However, the value being printed is 3 which is the 2nd definition of i.
So the variable label i is referring to two different instances in memory. One is being used as the loop count, to do the increment, and the other is the value being printed.
The only way I can somehow explain this is:
int i = 3 (the 2nd definition) is repeated in every recursive call. That instance of i is created when the function is called, and killed when the next recursive call is made. (Because of static scoping). printf uses this instance, as it is the latest definition(?)
When entering a new level of recursion, i++ is being done. Since there is no other way to resolve this i, it uses the static "instance" of i , which is still "alive" in the code as it was defined as static.
However, I'm unable to exactly put a finger on how this works..can anyone explain what's going on here, in the code and the memory?
How is the variable binding being done by the compiler here?
The inner scope wins.
Example:
int i = 1;
void foo() {
int i = 2; // hides the global i
{
int i = 3; // hides local i
}
}
This behavior is by design. What you can do is use different naming conventions for variable scopes:
global/statics
function arguments
locals
class/struct members
Some compilers will issue a warning if you hide a variable in the same function (e.g. function argument and regular local variable). So you the max warning level on your compiler.
The compiler will always use the most local version of a variable when more than one variable of that name exists.
Outside the loop, the first i is the only one that exists, so it is the one that is checked. Then a new i is created, with value 3. At this point whenever you talk about i it will assume you mean the second one, since that's more local. When you exit the loop, the second i will go out of scope and be deleted and so if you start talking about i again it will be the first one.
The {} of the if statement creates a new block scope and when you declare i in that scope you are hiding the i in the outer scope. The new scope does not start until { and thus the if statement is referring to the i in the outer scope.
Hiding is covered in the draft C99 standard section 6.2.1 Scopes of identifiers paragraph 4 says (emphasis mine):
[...]If an identifier designates two different entities in the same name
space, the scopes might overlap. If so, the scope of one entity (the inner scope) will be a
strict subset of the scope of the other entity (the outer scope). Within the inner scope, the
identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.