I consider to use a TRY/CATCH macro based on setjmp/longjmp for error handling. Otherwise some of my quite structued functions will be blown up by ugly if statements and loop flags.
The code is like this example:
int trycatchtest(int i)
{
int result = 0;
volatile int error = 100;
volatile uint32_t *var = NULL;
TRY
{
error = 0;
var = os_malloc(4);
*var = 11;
if (i) THROW( i );
}
FINALLY
{
result = *var;
}
END;
return result;
}
THROW is in fact the macro
#define TRY do { jmp_buf buf; switch( setjmp(buf) ) { case 0: while(1) {
#define FINALLY break; } default: {
#define END break; } } } while(0)
#define THROW(x) longjmp(buf, x)
The Problem:
When the exception is thrown (e.g. i=1) the pointer var is reset to NULL, although I used the volatile keyword, which should avoid using a register for it. From the debugger I see that is is still within a register and not in memory.
Did I make a mistake ?
EDIT:
I changed declaration of var into
uint32_t * volatile var = NULL;
This works ;-)
I do not really understand what is the difference:
volatile uint32_t * var = NULL;
means, that the VALUE is volatile, whereas the former declararation makes the pointer volatile?
u32 *volatile var makes the pointer volatile, while volatile u32 *var tells the compiler that the data at that address is volatile. So since the pointer is not volatile in the latter example, I wouldn't be surprised if your compiler optimized away the default case completely to something like result = NULL;.
It probably doesn't expect the setjmp wizardry, and these are notorious for being even "more spaghetti than goto".
Related
I use ARM-M4 with GCC for ARM (10_2021.10)
I have a problem where a pointer to struct displays the wrong values.
__copy_table_start__ is define in the linker file, I see it's location in the map file and this is how I found it's true value (and the values make sense, they are correct)
Here is my code
#pragma GCC optimize("O0")
static void DataInit(void)
{
typedef struct {
uint32_t const* src;
uint32_t* dest;
uint32_t wlen;
} __copy_table_t;
extern const __copy_table_t __copy_table_start__;
extern const __copy_table_t __copy_table_end__;
extern const __zero_table_t __zero_table_start__;
extern const __zero_table_t __zero_table_end__;
static volatile __copy_table_t const* pTable;
pTable = &__copy_table_start__;
for (; pTable < &__copy_table_end__; ++pTable) {
for(uint32_t i=0u; i<pTable->wlen; ++i) {
pTable->dest[i] = pTable->src[i];
}
}
}
And what I see in the debugger, right after pTable = &__copy_table_start__; is that:
__copy_table_start__.src = 0x14A0D380
__copy_table_start__.dest = 0x00100000
__copy_table_start__.wlen = 0x38A
pTable->src = 0x14A0D380
pTable->dest = 0x14A0D380
pTable->wlen = 0x14A0D380
How can that be?
UPDATE:
I did another experiment, I created another struct variable and a pointer to that variable and get the same results. first time I see this kind of behavior.
const __copy_table_t mine = {(uint32_t const*)0x12345678, (uint32_t *)0x00004545, 0x89890000};
static volatile __copy_table_t const* my_ptr;
my_ptr = &mine;
The result is that my_ptr->src = my_ptr->dest = my_ptr->wlen = 0x12345678
Apparently the problem is with Keil (the IDE).
It displays the wrong values.
When I created 3 new parameters and loaded the data to them:
my_src = (uint32_t)pTable->src;
my_dest = (uint32_t)pTable->dest;
my_len = (uint32_t)pTable->wlen;
Those parameters got the correct values.
What threw me off was that doing a single step in debug skipped the entire for loop (the first one), as if the internal for loop didn't do anything. It actually did what it was supposed to do, but one parameter that was supposed to be reset after that didn't update in the IDE.
There are many functions in the C libraries that require users to input with macros.
I wonder, if I have an array of strings, with contents of macros, like so:
char s[][3] = {"SIGINT", "SIGKILL", "SIGSTOP"};
How can I pass these strings as macros? (Like so:)
signal(s[0], do_something);
with do_something is a function pointer.
(and yes, technically I can pass ints in this case, but... hypothetically, ya know?)
EDIT:
As #RemyLebeau and SGeorgiades point out, the "SIGINT",... are aliases for integer consts, and therefore can be stored in an int array, like so:
int s[3] = {SIGINT, SIGKILL, SIGSTOP};
Although SGeorgiades and Remy Lebeau already gave you the answer, here is something that I've used in the past to allow conversion and pretty printing of signal numbers and names:
#include <stdio.h>
#include <signal.h>
#include <string.h>
struct sigfun {
int signo;
const char *signame;
};
#define SIGFUN(_sig) \
{ \
.signo = _sig, \
.signame = #_sig \
}
struct sigfun siglist[] = {
SIGFUN(SIGINT),
SIGFUN(SIGKILL),
SIGFUN(SIGSTOP),
// ...
{ .signo = 0, .signame = NULL }
};
#define SIGFORALL(_sig) \
_sig = siglist; _sig->signame != NULL; ++_sig
int
signame_to_signo(const char *signame)
{
struct sigfun *sig;
for (SIGFORALL(sig)) {
if (strcmp(sig->signame,signame) == 0)
break;
}
return sig->signo;
}
const char *
signo_to_signame(int signo)
{
struct sigfun *sig;
for (SIGFORALL(sig)) {
if (signo == sig->signo)
break;
}
return sig->signame;
}
UPDATE:
why not put for into SIGFORALL? –
tstanisl
For a few reasons ...
I've done that before (e.g.):
#define SIGFORALL(_sig) \
for (_sig = siglist; _sig->signame != 0; ++_sig)
SIGFORALL(sig) {
// do stuff
}
This tends to confuse certain IDEs and/or tools that parse the code without running it through the preprocessor.
It's also more difficult for programmers to quickly (without digesting the macro) skip over it.
They don't see a for and have trouble figuring out what SIGFORALL(sig) { does.
Is the macro a wrapper for if, for, or while?
With:
#define SIGFORALL(_sig) \
_sig = siglist; _sig->signame != 0; ++_sig
for (SIGFORALL(sig)) {
// do stuff
}
there is a better chance they can continue around the construct because they can understand (i.e. skip over) the for (...) [syntactically] without having to know what the macro is doing. That is, nobody has to "drill down" into the macro unless they wish to.
Another reason is that without the for in the macro, we can add extra code to the for loop's initialization and iteration expressions. It's more flexible.
For example, I've used a similar macro for linked list traversal and wanted to know the index/count of an element:
#define LLFORALL(_node) \
_node = nodelist; _node != NULL; _node = _node->next
int idx;
for (idx = 0, LLFORALL(node), ++idx) {
if (node->value == 5)
printf("found value at index %d\n",idx);
}
There's no absolute rule about this. Ultimately, it's a [personal] style preference.
Perhaps what you want instead is:
int s[3] = { SIGINT, SIGKILL, SIGSTOP };
signal(s[0], do_something);
I have this piece of code:
typedef enum myEnum_e
{
VAL0,
VAL1
} myEnum;
void func(void)
{
myEnum val = (myEnum) 0;
while(/*Do something*/)
{
val = val + ((myEnum)1); // <= Warning here
}
}
This piece of code produces the warning:
enumerated type mixed with another type
To clean this I ended up with:
void func(void)
{
myEnum val = (myEnum) 0;
while(/*Do something*/)
{
val = ((myEnum) val + 1); // <= NO Warning here
}
}
Could someone tell why the first form is incorrect?
I feel like the second is less meaningful than the first one.
I mean I would prefer to read:
Add 1, considered as a myEnum value, to val (and store the result in val)
Than
Store in val val + 1 considered as a myEnum value
Note: This is a TI C28x compiler (for TI C2000 MCUs).
Edit:
My real application is to define a custom UART communication for embedded software.
So here is what I have done:
typedef enum e_frame
{
FRAME_A,
FRAME_B,
FRAME_C,
FRAME_COUNT
} frame_e;
typedef enum e_frameId
{
FRAMEID_A = 0x0A,
FRAMEID_B = 0x42,
FRAMEID_C = 0xFF
} frameId_e;
const frameInfo_s FramesInfo[FRAME_COUNT] =
{
[FRAME_A] =
{
.id = MCM_FRAMEID_A,
// And other stuff
},
[FRAME_B] =
{
.id = MCM_FRAMEID_B,
// And other stuff
},
[FRAME_C] =
{
.id = MCM_FRAMEID_C,
// And other stuff
}
}
Finally the the ID to frame_e function:
frame_e UAR_FrameId2Frame(frameId_e id)
{
frame_e frame = (frame_e) 0;
while(FramesInfo[frame].id != id && frame < FRAME_COUNT)
{
frame = (MCM_frames_e)(frame + 1);
}
return frame;
}
I don't get any warnings here:
#include <stdio.h>
typedef enum myEnum_e
{
VAL0,
VAL1
} myEnum;
int main (int argc, char *argv[]) {
myEnum val = 0;
while( 1 /*Do something*/)
{
val = val + 1;
}
return 0;
}
Compiler: GCC 4.2.1
Compile command: gcc -Wall -pedantic x.c
It's a good thing that you are getting a warning.C is not a strictly typed language so you don't get errors when mixing types that can be coerced into one another. But mixing types has the potential to cause subtle runtime errors. So, although internally enums and integers are same types, you shouldn't be mixing them. You should consider using an enum increment variable initialized to 1.
First of all, having code with a lot of casts is not very pleasant to read, but well, that's just a matter of taste.
If you plan to do arithmetic you might want to explicitly define values for the enums. It's risky to do this anyway, because you could end up with an out-of-range values.
What if you add 3 to your VAL0?
Think about it, what does that mean? You've declared an enum, but the value that you now got is not a valid enum anymore. The reason to use an enum is mostly that you want to limit the number of possible values for an ordinal.
In your situation it makes more sense to have constants like VAL0 and VAL1.
Or, if all you needed was to iterate over your enum, you could do this:
typedef enum myEnum_e
{
VAL0,
VAL1,
// ...
VAL66
} myEnum;
for(int i=VAL0; i<=VAL66; i++) {
// do something here
}
I am doing some experiments with faking OOP in C, and I've stumbled upon a conundrum. In C++ I assume the compiler inserts destructors in the function epilogue, after the return statement has been executed.
Faking that in C would require the destructors be manually invoked in the appropriate order, but the problem is the return value might depend on some of those objects, so at one hand destruction cannot occur before the return statement, on the other hand statements after the return statements are never reached. And the issue becomes more complicated by the fact there might be multiple return statements from inside different blocks which require their own respective fake epilogues.
So the question is how can I possibly deal with it? It doesn't have to be nice, since it doesn't look like it can be...
So far the best I could come up was to "cache" the return value at the moment of its return, do all the cleanup and after all that simply return the cached value, but I wonder if a a more efficient solution might exist, and on a side note on how well the compiler will deal with this one to minimize its eventual overhead. Sort of:
T foo() {
T _retValue;
...
if (something) {
...
_retValue = someValue;
goto blockID_cleanup;
blockID_cleanup:
...
goto foo_cleanup; // goto parent block until function block
}
_retValue = somethingElse;
goto foo_cleanup;
foo_cleanup:
...
return _retValue;
}
Edit: Seems you're actually asking how objects are returned from functions, your question isn't 100% clear but here goes:
class A
{
public:
A(int value)
: mTest(value) {}
A operator + (const A& other)
{
return mTest + other.mTest;
}
operator int()
{
return mTest;
}
private:
int mTest = 0;
};
int foo()
{
A a(2);
A aa(4);
return a + aa;
}
This would become the following pesudo code:
int foo()
{
A a;
A aa;
a_ctor(&a, 2);
a_ctor(&aa, 4);
A temp;
a_copy(temp, a_operator_plus(a, aa)); // temp is another "instance"
// no need to worry about the dtors, the return value references nothing from these objects that isn't in scope anymore. If it did then this would be an error even in C++, so don't worry about that
a_dtor(&aa);
a_dtor(&a);
return temp.mTest;
}
C++ "generated" code will not call dtors "after" the return statement. Dtors are called just like any other function.
Assume the C++ code is:
class A
{
public:
A(const A&) = delete;
A& operator = (const A&) = delete;
A()
{
std::cout << "A ctor" << std::endl;
mExampleBuffer = new char[128]; // allocate resources example, we don't do anything with this..
}
~A()
{
std::cout << "A dtor" << std::endl;
delete[] mExampleBuffer;
}
private:
char* mExampleBuffer = nullptr; // in real code this would be a std::vector or std::unique_ptr
};
Then used as:
void foo()
{
A a;
return; // not required, but here for clarity
}
Then in C this would be:
struct A
{
// there is no "private" in C, so we need people to read this comment and not mess with mExampleBuffer
char* mExampleBuffer;
};
void a_ctor(A* thisPtr)
{
printf("A ctor\n");
thisPtr->mExampleBuffer = malloc(sizeof(char)*128);
if (!thisPtr->mExampleBuffer)
{
// TODO: In C++ this would throw, in C you're gonna have to use setlongjmp or some such to simulate it.. plus use some sort of "cleanupstack" to do the unwinding
}
}
void a_dtor(A* thisPtr)
{
printf("A dtor\n");
free(thisPtr->mExampleBuffer);
}
void foo()
{
A a = {};
a_ctor(&a);
a_dtor(&a); // nothing magic here, simply called before the return statement
return;
}
As you can see for lots of classes using "real" C++ with RAII this would become a complete nightmare.. also you're not taking into account that the actual generated code would probably inline this so that there is no "class", i.e it would look something like:
void foo()
{
printf("A ctor\n");
char* mExampleBuffer = malloc(sizeof(char)*128); // not sure if would remove this or not since not used :) didn't check
printf("A dtor\n");
free(mExampleBuffer);
return;
}
Hopefully this explains the dtor mechanism. Don't forget that with inheritance each dtor must call the base.
I'd like to illustrate a way to return complex object in C by mimicking move semantics to expand on Peter G. answer.
struct T {
char * data;
};
void swap(T * a, T * b) {
swap(&a.data, &b.data);
}
void destruct(T & d) {
free(d.data);
}
void foo(T * rv) {
T x = {"Valueable data"};
swap(rv, &x); //This is what return in C++ does
destruct(&x); //This happens, when function scope in C++ ends
}
void bar() {
T holder = {0};
foo(holder);
destruct(&holder);
}
Notice how allocation and deallocation of an object are always in the same scope.
In C++, a value returned from a function must not refer to memory of local objects, that would be an error. So, to me it looks like you're possibly trying to solve a problem not even a C++ compiler has to solve.
If on the other you want simply want to return a value computed by one of the local objects, first assign the value computed by the object to a local variable, destruct the object and then return the pre-computed return value.
In my company's code we have general get() and set() methods for interop between certain components. However, if I try to run PREfast I get inundated with warnings because PREfast doesn't realize that the get() method initializes the given parameters.
The problem is that since those methods are very general, they don't simply take a parameter (which I could mark with _Out_ or similar, but an array of structs which holds the data as to which data should be returned.
In code (greatly simplified):
typedef struct
{
int type;
int* data;
} ARGS;
void get(int count, ARGS* args)
{
for (int i = 0; i < count; i++)
*(args[i].data) = 42; // Actually handled by internal methods
}
// Sample Usage
void foo()
{
int value;
ARGS args[1];
args[0].type = 1234;
args[0].data = &value;
get(1, args);
// Do something with value
// PREfast complains that value is uninitialized (error C6001)
printf("%d", value);
}
Is there any way to annotate this so PREfast knows that args.data is initialized by get()? Or is this too complex for PREfast to handle?
EDIT: If I use get(1, &args), then the warning goes away. So there is some heuristic in PREfast which can handle this case, but I haven't found out if it is possible to trigger it externally:
void get2(int count, ARGS(* args)[1]) // Needs the size of args, or it won't compile below
{
for (int i = 0; i < count; i++)
*(*args)[i].data = 42; // Actually handled by internal methods
}
// Sample Usage
void foo2()
{
int value;
ARGS args[1];
args[0].type = 1234;
args[0].data = &value;
get2(1, &args);
// Do something with value
printf("%d", value);
}
This should fix the warning.
void foo()
{
int value=0;
...
}
Note that get() will be called in runtime only. Since, PREfast is a static analysis tool, it might report that the value is uninitialized. Nevertheless, initializing a variable before use is always a best practice in C.
Another way would be to use the PREfast suppress as below:
void foo()
{
int value;
ARGS args[1];
args[0].type = 1234;
args[0].data = &value;
get(1, args);
// Do something with value
// PREfast complains that value is uninitialized (error C6001)
#pragma prefast(suppress:C6001 , "PREfast noise: the variable value will be initialized by get method in a line above")
printf("%d", value);
}
It suppresses the warnings in the next line after the suppress statement.
Also, do add the following code in you header files(or source files) just before using the pragma prefast in your code:
#ifndef _PREFAST_
#pragma warning(disable:4068)
#endif
to avoid 4068 warning to be flagged. NOTE: pragma prefast is an extension to the PREfast AST compiler only and may not be supported by other compilers.