volatile variables as argument to function - c

Having this code:
typedef volatile int COUNT;
COUNT functionOne( COUNT *number );
int functionTwo( int *number );
I can't get rid of some warnings..
I get this warning 1 at functionOne prototype
[Warning] type qualifiers ignored on
function return type
and I get this warning 2, wherever I call functionTwo with a COUNT pointer argument instead of an int pointer
[Warning] cast discards qualifiers
from pointer target type
obviously variables/pointers can't be "cast" to volatile/un-volatile.. but every arguments must be specified as volatile too? so how can I use any library function if it's already defined for non-volatile variable?
EDIT: Using gcc -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wextra -Wstrict-prototypes -Wmissing-prototypes …
EDIT: After Jukka Suomela advice this is a code sample for warning two
typedef volatile int COUNT;
static int functionTwo(int *number) {
return *number + 1;
}
int main(void) {
COUNT count= 10;
count = functionTwo(&count);
return 0;
}

The volatile keyword was designed to be applied to objects that represent storage and not to functions. Returning a volatile int from a function does not make much sense. The return value of a function will not be optimized away (with the possible exception of inlined functions, but that's another case altogether...), and no external actor will be modifying it. When a function returns, it passes a copy of the return value to the calling function. A copy of a volatile object is not itself volatile. Therefore, attempting to return a volatile int will result in a copy, casting it down to a non-volatile int, which is what is triggering your compiler messages. Returning a volatile int* might be useful, but not a volatile int.
Passing an object by value into a function makes a copy of the object, thus using a volatile int as a function parameter necessarily involves a conversion that ignores a qualifier. Passing a volatile by address is perfectly reasonable, but not by value.
According to the C spec, the behavior of volatile is completely implementation-dependent, so YMMV.
Are you using volatile in this way to try to defeat some sort of compiler optimization? If so, there is probably a better way to do it.
Edit:
Taking into account the updates to your question, it appears that you may be able to approach this in a different way. If you are trying to defeat compiler optimizations, why not take the direct approach and simply tell the compiler not to optimize some things? You can use #pragma GCC optimize or __attribute__((optimize)) to give specific optimization parameters for a function. For example, __attribute__((optimize(0))) should disable all optimizations for a given function. That way, you can keep your data types non-volatile and avoid the type problems you are having. If disabling all optimizations is a bit too much, you can also turn individual optimization options on or off with that attribute/pragma.
Edit:
I was able to compile the following code without any warnings or errors:
static int functionTwo(int *number) {
return *number + 1;
}
typedef union {
int i;
volatile int v;
} fancy_int;
int main(void) {
fancy_int count;
count.v = 10;
count.v = functionTwo(&count.i);
return 0;
}
This hack"technique" probably has some kind of odd side-effects, so test it thoroughly before production use. It's most likely no different than directly casting the address to a (int*), but it doesn't trigger any warnings.

It's possible that I am way off base here but volatile isn't something normally associated with stack memory region. Therefore I'm not sure if the following prototype really makes much sense.
volatile int functionOne(volatile int number);
I'm not sure how a returned integer can be volatile. What's going to cause the value of EAX to change? The same applies to the integer. Once the value is pushed onto the stack so that it can be passed as a parameter what's going to change its value?

I don't understand why you'd want to have the volatile qualifier on a function return type. The variable that you assign the function's return value to should be typed as a volatile instead.
Try making these changes:
typedef int COUNT_TYPE;
typedef volatile COUNT_TYPE COUNT;
COUNT_TYPE functionOne( COUNT number );
COUNT_TYPE functionTwo( COUNT_TYPE number );
And when calling functionTwo(), explicitly cast the argument:
functionTwo( (COUNT_TYPE)arg );
HTH,
Ashish.

If I compile
typedef volatile int COUNT;
static int functionTwo(int number) {
return number + 1;
}
int main(void) {
COUNT count = 10;
count = functionTwo(count);
return 0;
}
using
gcc -std=c99 -pedantic -Wall -Wshadow -Wpointer-arith -Wcast-qual \
-Wextra -Wstrict-prototypes -Wmissing-prototypes foo.c
I don't get any warnings. I tried gcc 4.0, 4.2, 4.3, and 4.4. Your warningTwo sounds like you are passing pointers, not values, and that's another story...
EDIT:
Your latest example should be written like this; again, no warnings:
typedef volatile int COUNT;
static int functionTwo(COUNT *number) { return *number + 1; }
int main(void) { COUNT count = 10; count = functionTwo(&count); return 0; }
EDIT:
If you can't change functionTwo:
typedef volatile int COUNT;
static int functionTwo(int *number) { return *number + 1; }
int main(void) {
COUNT count= 10;
int countcopy = count;
count = functionTwo(&countcopy);
return 0;
}
Note that any access to a volatile variable is "special". In the first version with functionTwo(COUNT *number), functionTwo knows how to access it properly. In the second version with countcopy, the main function knows how to access it properly when assigning countcopy = copy.

It's possible that those who wrote it wanted to be sure that all the operations are atomic, and declared all int variables as volatile (is it a MT application with poor syncronization?), so all the ints from the code are declared as volatile "for consistency".
Or maybe by declaring the function type as volatile they expect to stop the optimizations of the repeated calls for pure functions? An increment of a static variable inside the function would solve it.
However, try to guess their original intention, because this just does not make any sense.

Related

Accessing array items generically through pointer to array of chars?

If I'm writing a generic algorithm, am I allowed to alias an array of unknown type as a pointer to an array where each element is the size provided without invoking undefined behavior?
For example, is there UB in the following code?
typedef void (*action_t)(const void *item);
void do(void *array, size_t eltCount, size_t eltSize, action_t action)
{
// Convenient typedef.
typedef char element[eltSize];
element *elts = array;
element *end = elts + eltCount;
for (; elts != end; elts++) {
action(elts);
}
}
I know I can do this:
char *elts = array;
char *end = elts + eltCount * eltSize;
for (; elts != end; elts += eltSize) {
action(elts);
}
But the first bit of code seems more idiomatic to me since the compiler does the pointer arithmetic for me. The function above compiles without warnings using both gcc and clang (relevant compilation flags are -std=c99 -O3 -fstrict-aliasing -pedantic-errors -Wextra -Wall). I'm also wondering about strict aliasing, but as far as I can tell, it seems like I'm not breaking it here since objects are allowed to be used indirectly via char*.
In C, a typedef doesn't introduce a new type. It just names a construct. The name and its definition are interchangeable. (The same is not true for, say, struct, where there is no way to express the structure's definition other than by its name.)
So, as long as you're only talking about some form of char * -- which as you know, is special because any data pointer can be converted to it -- then you're relying on defined behavior.

The compiler gives no warning on returning local pointer

I am using code blocks with GCC compiler. In the code below, compiler gives warning while returning local reference but no warning on returning local pointer though both are same thing. Why ?
I understand these variables are local and will be destroyed as soon as control returns from the function. De-referencing these would result in undefined behavior.
int *check(int j)
{
int *q;
q= &j;
return q; // No warning
//return &j; // Warning
}
First, because warnings are optional.
Second, this code
int *q
...
return q;
doesn't return a the address of a local variable directly. You wrote the explicit code that made the pointer point to an address that becomes invalid when the function returns. No compiler can be expected to save you from that.
Andrew I would have to disagree.
According to gcc documentation
-Wno-return-local-addr
Do not warn about returning a pointer (or in C++, a reference) to a variable that goes out of scope after the function returns.
Edit: I redact my earlier claim. Turns out GCC does disappoint me. Apparently that error only works if you directly return something that will be cleared from the stack. If you store it in a temporary variable GCC does not check that even though it has more then enough information to do so just my checking if the pointer leads to some address between %EBP and %ESP
Here is some code I made to test it real quick to confirm that GCC doesn't check. If you run this with -Wall it produces no error however if you return &val it will produce two warnings (one for the return one for j not being used). I feel like GCC should recursively check that my returned pointer stays in scope rather then just checking the immediate value.
#include <stdio.h>
#include <stdlib.h>
int * myFunc(int val){
int *j;
j=&val;
return j; //Should not work val goes out of scope
}
int someFuncToClearMyStack(int a, int b, int c){
int d;
int e;
d=a+b+c;
e=c-b-a;
d=d-e;
return d;
}
int main(){
int *i;
int j;
i=myFunc(10);
printf("%i\n",*i);
j=someFuncToClearMyStack(3,4,5);
printf("%i %i",*i,j);
return 0;
}

Loop unrolling in inlined functions in C

I have a question about C compiler optimization and when/how loops in inline functions are unrolled.
I am developing a numerical code which does something like the example below. Basically, my_for() would compute some kind of stencil and call op() to do something with the data in my_type *arg for each i. Here, my_func() wraps my_for(), creating the argument and sending the function pointer to my_op()... who’s job it is to modify the ith double for each of the (arg->n) double arrays arg->dest[j].
typedef struct my_type {
int const n;
double *dest[16];
double const *src[16];
} my_type;
static inline void my_for( void (*op)(my_type *,int), my_type *arg, int N ) {
int i;
for( i=0; i<N; ++i )
op( arg, i );
}
static inline void my_op( my_type *arg, int i ) {
int j;
int const n = arg->n;
for( j=0; j<n; ++j )
arg->dest[j][i] += arg->src[j][i];
}
void my_func( double *dest0, double *dest1, double const *src0, double const *src1, int N ) {
my_type Arg = {
.n = 2,
.dest = { dest0, dest1 },
.src = { src0, src1 }
};
my_for( &my_op, &Arg, N );
}
This works fine. The functions are inlining as they should and the code is (almost) as efficient as having written everything inline in a single function and unrolled the j loop, without any sort of my_type Arg.
Here’s the confusion: if I set int const n = 2; rather than int const n = arg->n; in my_op(), then the code becomes as fast as the unrolled single-function version. So, the question is: why? If everything is being inlined into my_func(), why doesn’t the compiler see that I am literally defining Arg.n = 2? Furthermore, there is no improvement when I explicitly make the bound on the j loop arg->n, which should look just like the speedier int const n = 2; after inlining. I also tried using my_type const everywhere to really signal this const-ness to the compiler, but it just doesn't want to unroll the loop.
In my numerical code, this amounts to about a 15% performance hit. If it matters, there, n=4 and these j loops appear in a couple of conditional branches in an op().
I am compiling with icc (ICC) 12.1.5 20120612. I tried #pragma unroll. Here are my compiler options (did I miss any good ones?):
-O3 -ipo -static -unroll-aggressive -fp-model precise -fp-model source -openmp -std=gnu99 -Wall -Wextra -Wno-unused -Winline -pedantic
Thanks!
Well, obviously the compiler isn't 'smart' enough to propagate the n constant and unroll the for loop. Actually it plays it safe since arg->n can change between instantiation and usage.
In order to have consistent performance across compiler generations and squeeze the maximum out of your code, do the unrolling by hand.
What people like myself do in these situations (performance is king) is rely on macros.
Macros will 'inline' in debug builds (useful) and can be templated (to a point) using macro parameters. Macro parameters which are compile time constants are guaranteed to remain this way.
It's faster, because your program does not assign memory to the variable.
If you don't have to perform any operations on unknown values they are treated as if they were #define constant 2 with type checking. They are just added while the compilation.
Could you please chose one of the two tags (I mean C or C++), it's confusing, because the languages treat const values differently - C treats them like normal variables which value just can't be changed, and in C++ they do or don't have memory assigned depending on the context (if you need their address or if you need to compute them when the program is running, then memory is assigned).
Source: "Thinking in C++". No exact quote.

How to determine the length of a function?

Consider the following code that takes the function f(), copies the function itself in its entirety to a buffer, modifies its code and runs the altered function. In practice, the original function that returns number 22 is cloned and modified to return number 42.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ENOUGH 1000
#define MAGICNUMBER 22
#define OTHERMAGICNUMBER 42
int f(void)
{
return MAGICNUMBER;
}
int main(void)
{
int i,k;
char buffer[ENOUGH];
/* Pointer to original function f */
int (*srcfptr)(void) = f;
/* Pointer to hold the manipulated function */
int (*dstfptr)(void) = (void*)buffer;
char* byte;
memcpy(dstfptr, srcfptr, ENOUGH);
/* Replace magic number inside the function with another */
for (i=0; i < ENOUGH; i++) {
byte = ((char*)dstfptr)+i;
if (*byte == MAGICNUMBER) {
*byte = OTHERMAGICNUMBER;
}
}
k = dstfptr();
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
The code now relies on just guessing that the function will fit in the 1000 byte buffer. It also violates rules by copying too much to the buffer, since the function f() will be most likely a lot shorter than 1000 bytes.
This brings us to the question: Is there a method to figure out the size of any given function in C? Some methods include looking into intermediate linker output, and guessing based on the instructions in the function, but that's just not quite enough. Is there any way to be sure?
Please note: It compiles and works on my system but doesn't quite adhere to standards because conversions between function pointers and void* aren't exactly allowed:
$ gcc -Wall -ansi -pedantic fptr.c -o fptr
fptr.c: In function 'main':
fptr.c:21: warning: ISO C forbids initialization between function pointer and 'void *'
fptr.c:23: warning: ISO C forbids passing argument 1 of 'memcpy' between function pointer and 'void *'
/usr/include/string.h:44: note: expected 'void * __restrict__' but argument is of type 'int (*)(void)'
fptr.c:23: warning: ISO C forbids passing argument 2 of 'memcpy' between function pointer and 'void *'
/usr/include/string.h:44: note: expected 'const void * __restrict__' but argument is of type 'int (*)(void)'
fptr.c:26: warning: ISO C forbids conversion of function pointer to object pointer type
$ ./fptr
Hello 42!
$
Please note: on some systems executing from writable memory is not possible and this code will crash. It has been tested with gcc 4.4.4 on Linux running on x86_64 architecture.
You cannot do this in C. Even if you knew the length, the address of a function matters, because function calls and accesses to certain types of data will use program-counter-relative addressing. Thus, a copy of the function located at a different address will not do the same thing as the original. Of course there are many other issues too.
In the C standard, there is no notion of introspection or reflection, thus you'd need to devise a method yourself, as you have done, some other safer methods exists however.
There are two ways:
Disassemble the function (at runtime) till you hit the final RETN/JMP/etc, while accounting for switch/jump tables. This of course requires some heavy analysis of the function you disassemble (using an engine like beaEngine), this is of course the most reliable, but its slow and heavy.
Abuse compilation units, this is very risky, and not fool proof, but if you know you compiler generates functions sequentially in their compilation unit, you can do something along these lines:
void MyFunc()
{
//...
}
void MyFuncSentinel()
{
}
//somewhere in code
size_t z = (uintptr_t)MyFuncSentinel - (uintptr_t)MyFunc;
uint8_t* buf = (uint8_t*)malloc(z);
memcpy(buf,(char*)MyFunc,z);
this will have some extra padding, but it will be minimal (and unreachable). although highly risky, its a lot faster that the disassemble method.
note: both methods will require that the target code has read permissions.
#R.. raises a very good point, your code won't be relocatable unless its PIC or you reassasmble it in-place to adjust the addresses etc.
Here is a standards compliant way of achieving the result you want:
int f(int magicNumber)
{
return magicNumber;
}
int main(void)
{
k = f(OTHERMAGICNUMBER);
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
Now, you may have lots of uses of f() all over the place with no arguments and not want to go through your code changing every one, so you could do this instead
int f()
{
return newf(MAGICNUMBER);
}
int newf(int magicNumber)
{
return magicNumber;
}
int main(void)
{
k = newf(OTHERMAGICNUMBER);
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
I'm not suggesting this is a direct answer to your problem but that what you are doing is so horrible, you need to rethink your design.
Well, you can obtain the length of a function at runtime using labels:
int f()
{
int length;
start:
length = &&end - &&start + 11; // 11 is the length of function prologue
// and epilogue, got with gdb
printf("Magic number: %d\n", MagicNumber);
end:
return length;
}
After executing this function we know its length, so we can malloc for the right length, copy and editing the code, then executing it.
int main()
{
int (*pointerToF)(), (*newFunc)(), length, i;
char *buffer, *byte;
length = f();
buffer = malloc(length);
if(!buffer) {
printf("can't malloc\n");
return 0;
}
pointerToF = f;
newFunc = (void*)buffer;
memcpy(newFunc, pointerToF, length);
for (i=0; i < length; i++) {
byte = ((char*)newFunc)+i;
if (*byte == MagicNumber) {
*byte = CrackedNumber;
}
}
newFunc();
}
Now there's another bigger problem though, the one #R. mentioned. Using this function once modified (correctly) results in segmentation fault when calling printf because the call instruction has to specify an offset which will be wrong. You can see this with gdb, using disassemble f to see the original code and x/15i buffer to see the edited one.
By the way, both my code and yours compile without warnings but crash on my machine (gcc 4.4.3) when calling the edited function.

Initialization of a pointer array

I'm facing a problem initializing an array with pointers to members of a structure. The structure members have to be accessed through a structure pointer. The reason for this is we initialize the pointer at runtime to a memory mapped address location. The following code snippet is an example of the problem;
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
long* lp;
}T;
typedef struct
{
long l;
}F;
F* f;
T t[] =
{
{ &f->l }
};
void init (void)
{
f = (F*) 0x08000100;
}
int main (void)
{
init();
return EXIT_SUCCESS;
}
The compiler output is the following;
gcc -O0 -g3 -Wall -c
-fmessage-length=0 -osrc\Test.o ..\src\Test.c ..\src\Test.c:18:
error: initializer element is not constant
..\src\Test.c:18: error: (near initialization for `t[0].lp')
..\src\Test.c:18: error: initializer element is not constant
..\src\Test.c:18: error: (near initialization for `t[0]')
Build error occurred, build is stopped
The problem here is we initialize the pointer at runtime, the compiler doesn't know where it can find the structure members. We cannot work around the structure pointer as we don't wan't to use the linker script for this.
Any ideas how to get around this one?
T t[] =
{
{ &f->l }
};
The address of an element (e.g. &f->l) is only known at run-time.
Such a value cannot be used for compile-time initialization (which is what's being done here).
The t[] array cannot be filled out until runtime - because the address of F isn't known until runtime.
You could initialize T[] to {NULL} and patch it in post-init.
Another approach is to initialize the members of T to just simply be the offset within the structure, and after you init f, to walk through the array and adjust the pointer locations by adding the address of f. This technique is similar to what is often used in linking.
Something like this:
#define MEMBER_OFFSET_OF(a,b) &(((a*)0)->b)
T t[] =
{
{(long*)MEMBER_OFFSET_OF(F, l)}
};
const int numElementsInT = sizeof(t) / sizeof(t[0]);
void init()
{
f = (F*) 0x08000100;
for (int i= 0; i < numElementsInT; i++)
{
t[i].lp += (unsigned int)f;
}
}
Lets imagine that you could use non-constant data to initialize a global: you still have a huge problem.
When t is initialized, f still has an indeterminate value: this happens before init() executes and assigns your magic address. Because of this, even if you could use &f->l, you'd have to reset all places it's been used, anyway.
Technically speaking for a C90 compiler there is no way around this. For the initialization idiom,
declarator = initialization sequence
the initialization sequence needs to be a constant expression, i.e. one which can be computed at compile-time or at link-time. So,
int a;
int *b[] = { &a };
works, while
void foo() {
int a;
int *b[] = { &a };
}
will not because the address of the automatic a isn't computable before runtime.
If you switch to C99, the latter will work. Your code however still is beyond what a C99 compiler can precompute. If you switch to C++ your code would work, at least Comeau doesn't object.
Edit: of course Roger is correct in that this doesn't solve your problem of having an incorrect dereferencing through a NULL pointer.

Resources