I would have posted this in the spinroot Bug Reports, but the spinroot forum is not currently accepting new users... If someone out there in charge of that is reading this, please let me in :)
Something very odd is happening when I try to use the select statement. Promela does not allow select() to be called on the field of a struct, so I have to make a temporary variable like this:
typedef someStruct {
int someField;
}
someStruct struct;
inline SetSelect() {
int temp;
select(temp: -1 .. 1);
struct.someField = temp;
}
init{
SetSelect();
}
This runs fine. I tested it and struct.someField is correctly set to either -1, 0, or 1. However, when I try to just put the inlined code straight into the init() process, I get a syntax error. The code looks like this:
typedef someStruct {
int someField;
}
someStruct struct;
init{
int temp;
select(temp: -1 .. 1);
struct.someField = temp;
}
And the error message is:
spin: select_test.pml:9, Error: syntax error saw ''-' = 45'
BUG:
Indeed, it looks like a bug for version 6.4.6 of Spin.
(The bug is fixed in version 6.4.7)
Interestingly, You can make it go away by simply writing temp : instead of temp:.
I suggest you to contact Gerard Holzmann for filing a bug report. I would also mention the fact that select does not seem to work with a struct field, perhaps that can be fixed too (even if it might be by design).
SUGGESTION:
I am not entirely happy of creating an alias variable to get around the issue of the built-in select function with struct fields. Since the implementation of select is rather trivial, as can be found in the docs, I would introduce a novel inline function to replace the built-in select function:
typedef Struct
{
int field;
}
inline my_select (var, lower, upper)
{
var = lower;
do
:: var < upper -> var++;
:: break;
od;
}
init
{
Struct st;
my_select(st.field, -1, 1);
printf("%d\n", st.field);
}
Related
Why is it that in the source code in the SDK for LPNMITEMACTIVATE it is defined with the asterix to the left?
typedef struct tagNMITEMACTIVATE
{
NMHDR hdr;
int iItem;
int iSubItem;
UINT uNewState;
UINT uOldState;
UINT uChanged;
POINT ptAction;
LPARAM lParam;
UINT uKeyFlags;
} NMITEMACTIVATE, *LPNMITEMACTIVATE;
I am always used to the pointer being on the right. Either way, code like:
const LPNMITEMACTIVATE pNMItem = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
Will still flag a const (C26462) warning:
If I change the code to:
const NMITEMACTIVATE* pNMItem = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
The warning will go away.
I tried this with Visual Studio 2022, first of all, warning C26462 was not enabled by default. Perhaps you are using an earlier release, or there is something odd with my installation.
After manually enabling the warning, I could make that warning go away by assigning pNMItem more than once:
LPNMITEMACTIVATE pNMItem = nullptr;
pNMItem = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
How is this useful?
Or it can be fixed as suggested in other answers. But you may have additional problem because pNMHDR was probably declared as LPNMHDR, so you have to rewrite more lines:
NMHDR hdr = { 0 };
const NMHDR* pNMHDR = reinterpret_cast<NMHDR*>(&hdr);
const NMITEMACTIVATE* pNMItem = reinterpret_cast<const NMITEMACTIVATE*>(pNMHDR);
This can be a big waste of time. Note, the extra compliance is recommended if you are writing code that's supposed to run on any system. But MFC is tied to Windows so this isn't really an issue. MFC and Windows are still using that "long pointer" crap that's left over from 16-bit Windows, they are not compliant themselves, so consider turning off some of these warnings.
This is standard C/C++
Like in this (not runnable) code snippet:
typedef int *LPINT;
// typedef int* LPINT; // you could write this, it's exactly the
// the same as above
int main()
{
LPINT pint;
int* pint2;
*pint = *pint2;
}
pint and pint2 are both pointers to int. BTW this is hiding a pointer type behind a typedef, which is a bad idea (but was considered as a good idea in old MS days), but lots of Microsoft headers still have these typedef sometype *LPsometype; typedefs for compatibility reasons.
Another example which is closer to the MS header you're refering to:
This:
typedef struct tagNMITEMACTIVATE
{
int hdr;
int iItem;
} NMITEMACTIVATE, *LPNMITEMACTIVATE;
is equivalent to this:
typedef struct tagNMITEMACTIVATE
{
int hdr;
int iItem;
} NMITEMACTIVATE;
typedef struct tagNMITEMACTIVATE *LPNMITEMACTIVATE;
For pointer const can be applied to the type the pointer points at:
const NMITEMACTIVATE* p;
or
NMITEMACTIVATE const* p;
Or it can be applied to the pointer variable itself:
NMITEMACTIVATE* const p;
Now if you have typedef:
typedef NMITEMACTIVATE *PNMITEMACTIVATE;
The const would not apply to the type being pointed at. Either way it is the pointer itself is constant:
const PNMITEMACTIVATE p;
PNMITEMACTIVATE const p;
To avoid this confusion, prefer not to use raw pointer typedefs (and not to define them).
Is it possible to EXPORT_SYMBOL() a struct that contains a kmalloc array? If yes, what are the things that I need to keep in mind?
This is a psuedo code of what I want to do.
struct test {
int a;
...
uint64_t* data;
}
struct test foo;
EXPORT_SYMBOL(foo);
...
In module1_kthread1_func() I have:
int module1_kthread1_func(void *foo){
...
foo->data = kmalloc(SIZE, GFP_KERNEL);
...
foo->data[var] = 1243;
var++;
...
}
In module2_kthread2_func() I have:
...
extern struct test foo;
...
int module2_kthread2_func(void* foo){
...
for (i=0; i<SIZE; i++)
printk(KERN_INFO "Variable value of %d is %llu", i, foo->data[var]);
...
}
It's definitely possible, yes.
You need to be careful and make sure that code that uses it knows that some of the fields might not be available before they are allocated. That is, check if they are NULL first instead of directly accessing them.
You might want to declare the structure with an explicit initializer, just so that it is obvious what is going on:
struct test foo = {
.a = 123,
.data = NULL // Initialized by function X when Y
};
EXPORT_SYMBOL(foo);
If such fields are compulsory for the structure to be used, you might want to initialize them early on (see here).
I coded an Arduino project for my son and learned about C in the process. All works fine but after dividing up the code into ten files and grouping the variables into structs in each file I'm not able to solve one wish for clarity. We need to empirically determine the best size of an array for storing and averaging port reads so this is what I want:
struct Alarms {
// Configurable parameters
const unsigned int number_of_reads = 24;
// State variables
int reads[number_of_reads]; // Error: invalid use of non-static data member 'Alarms::num_of_reads'
};
It’s simple but doesn't work. I tried flexible array members until I found that that feature is not supported in C++. Arduino compiles with C++. I tried many examples of the 'struct hack' but they all returned errors like this one:
struct Alarms {
// Configurable parameters
int number_of_reads = 24;
// State variables
int reads[];
} ar;
void setup_alarm() {
ar.reads = malloc(sizeof(int) * ar.number_of_reads); // Error: incompatible types in assignment of 'void*' to 'int [0]'
}
That looked promising but I suspect my ignorance is glowing brightly. Most struct hack examples call for declaring the struct and later initializing the struct variables. I’m hoping to not duplicate the struct.
I considered splitting the struct but that would be error prone and, well, another compile error:
struct Alarms2 {
int reads[ar.num_of_reads]; // Error: array bound is not an integer constant before ']' token
} ar2;
An alternative is to size the array and get the size later but it needs an explanation:
struct Alarms {
// Configurable parameters
int reads[ 24 ]; // Put number of reads to average between brackets
// State variables
int number_of_reads;
};
void setup_alarm() {
ar.number_of_reads = sizeof(ar.reads) / sizeof(ar.reads[0]); // this works
}
Is there a way to work the struct hack or some similar solution in Arduino to like achieve the first example?
The size of the struct must be known at compilation time. Const data types in structs can change per instance of the structure, that is why you are getting the invalid use of non-static data member 'Alarms::num_of_reads' when you try to initialize your array. The best way to solve this is to have an init_alarm and destroy_alarm functions. Like so ...
#include <stdio.h>
#include <stdlib.h>
#define DEFAULT_NUM_OF_READS (24)
struct alarm {
// Configurable parameters
const int number_of_reads;
// State variables
int *reads;
};
void init_alarm(struct alarm *alarm)
{
alarm->reads = (int *) malloc(alarm->number_of_reads * sizeof(int));
}
void destroy_alarm(struct alarm *alarm)
{
free(alarm->reads);
}
int main(int argc, char **argv)
{
// When we create our struct, set number_of_reads to default
struct alarm alarm = {.number_of_reads = DEFAULT_NUM_OF_READS, .reads = NULL};
init_alarm(&alarm);
alarm.reads[0] = 13;
alarm.reads[23] = 100;
printf("alarm.reads[0] = %d, alarm.reads[23] = %d\n", alarm.reads[0], alarm.reads[23]);
destroy_alarm(&alarm);
return 0;
}
Note: Inorder to use the designated initializer to initialize a structure you must compile with ANSI (C99) like so ...
gcc --std=c99 test.c -o test
I'm having trouble with declaration and initialization of a struct in Vectors CANoe CAPL. I already know structs from C/C++ but it seems the declaration is a little different in CAPL.
The Vector help function isn't really revealing.
I have a number of CAN IDs (e.g. 0x61A). Every CAN ID is a different number of Signal IDs (e.g. 0xDDF6) assigned. I want to read out cyclic the Signal ID from the CAN IDs and plan to organize this in a convoluted struct.
I already tried out different types of declaration and initialization but every time I get a parse error.
Can you please give me a helping hand for my problem?
Any other ideas to organize my values unlike a struct?
Thank you and regards!
From the CAPL documentation:
Structured types can be declared in CAPL in a similar way to C...
... they may only be used in CAPL programs with CANoe from version 7.0 Service Pack 3.
Example:
variables
{
/* declarating a struct */
struct MyData {
int i;
float f;
};
}
on start
{
/* defining a struct variable and initiliazing the elements */
struct MyData data = {
i = 42,
f = 1.32
};
/* accessing the struct elements */
write("i=%d, f=%f", data.i, data.f);
}
Output:
i=42, f=1.320000
I had a flaw in struct access. Tried to initialize the struct paramters right in the variable declaration routine, not in the on startroutine.
Working code for my multiple data access is now:
variables
{
struct Veh_Database
{
dword ECU;
dword ParamID[8][2];
};
struct Veh_Database ECU_Info[12];
}
on start
{
ECU_Info[0].ECU = 0x1A;
ECU_Info[0].ParamID[0][0] = 0xDD;
ECU_Info[0].ParamID[0][1] = 0xF6;
/* ... */
ECU_Info[1].ECU = 0x12;
ECU_Info[1].ParamID[0][0] = 0xDE;
ECU_Info[1].ParamID[0][1] = 0x9C;
/* ... */
}
Thanks for your help!
Just for completeness: It is also possible to initialize a struct in the variable declaration:
variables
{
struct myStruct
{
dword val;
dword arr[8];
};
struct myStruct myInstance = {1, {1,2,3,4,5,6,7,8}};
}
(tested on CANoe 10)
CAPL allows initialization of variables structures at declaration also at Onstart procedure but we have to follow correct syntax. here is example code
variables
{
struct mydata
{
int a;
int b;
} ak={5,3};
}
on start
{
write("Initial values are %d, %d",ak.a,ak.b);
ak.a=10;
ak.b=20;
write("values after update are %d, %d", ak.a,ak.b);
}
find more details in following video
https://www.youtube.com/watch?v=hRfSqZBZVHA
In this code snippet, the Init() function acts as a on-demand initializer that fills in all member variables of the structure. This is done to avoid calling default constructors all members of a large array on the stack:
struct Foo {
int m_Member;
void Init(int i);
};
void Foo::Init(int i) {
m_Member = i;
// Many other members initialized here.
}
void SomeFunction(int n) {
Foo buffer[64];
assert(n <= 64);
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
buffer[i].Init(i * 3);
}
// Use buffer[0] - buffer[n-1] somehow.
}
This triggers a static analysis error in VS2012 with /analyze:
warning C6001: Using uninitialized memory 'buffer'.: Lines: 17, 19, 20
I'm looking for a way to annotate Foo::Init() so that this warning doesn't occur. There are plenty of other ways to make the warning go away, including:
Adding an empty constructor
Moving Init() to the constructor and calling placement new in the loop
But I'd like to avoid changing the structure of the code.
I've tried the following annotation without success:
void _At_(this, _Out_) Init();
This syntax is accepted, but only changes the warning to be:
warning C6001: Using uninitialized memory 'buffer'.: Lines: 18, 20, 21
warning C6001: Using uninitialized memory 'buffer[BYTE:0]'.: Lines: 18, 20, 21
Does anyone know how I can declare the intent of this Init() function to the static analysis engine?
Your question is somewhat elusive. You have shown SomeFunction taking int, but want annotation for method Init or constructor.
The warning shown is absolutely correct, assert won't hide the warning. You need to put if to check if n is greateer than 64 and reset n (or do something else, but not to loop when n>=64).
For annotation you need to use __in_bcount or similar alternative. An example:
bool SetBuffer(__in_bcount(8) const char* sBuffer);
Whichs says sBuffer is of 8 bytes (not elements).
You can read this this article for more information.
Too ugly to add an extra helper?
struct Foo {
int m_Member;
void Init(int i);
};
void Foo::Init(int i) {
m_Member = i;
// Many other members initialized here.
}
void Initialize(__in_bcount(sizeof(Foo) * n) Foo* buffer, int n) {
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
buffer[i].Init(i * 3);
}
}
void SomeFunction(int n) {
Foo buffer[64];
assert(n <= 64);
Initialize(buffer, n);
// Use buffer[0] - buffer[n-1] somehow.
}
I found a work around by implementing a function to index the array. I flagged the return value as invalid so that this new function only escapes the uninitialized value check in the specific case where the return value is only used to initialize. I've only tested this in VS2017.
#define _Ret_invalid_ _SAL2_Source_(_Ret_invalid_, (), _Ret1_impl_(__notvalid_impl))
template <typename T>
_Ret_invalid_ T& UninitialzedIndex(T* pt, int index)
{
return pt[index];
}
Then, where the value is indexed, I call UninitialzedIndex instead of operator[]
void SomeFunction(int n) {
Foo buffer[64];
if (n <= 64)
return;
// Explicitly initialize what is needed.
for (int i = 0; i < n; ++i) {
UninitialzedIndex(buffer, i).Init(i * 3);
}
// Use buffer[0] - buffer[n-1] somehow.
}
Just add a default constructor (that calls Init()). What is wrong with that?
[Edit] The root problem is not how to lie to the static analyzer or your compiler. It is how to enforce that you don't leave foo in an uninitialized state. There is nothing wrong with adding a default constructor. I'd say the desire to NOT do it imposes risk.
Perhaps some client will use that poorly constructed foo class (Long after you wrote it and long after you are gone) and perhaps they will forget to call .Init() ?? What then? They will be left with data that is uninitialized.
If you are looking to enforce that rule, no amount of static analysis will help you there.
Take care of the foundation before you put on the roof.