C unused pointer parameter - c

I have found the following function definition in Linux source:
static int __ref kernel_init(void *unused)
{
int ret;
kernel_init_freeable();
/* need to finish all async __init code before freeing the memory */
async_synchronize_full();
ftrace_free_init_mem();
free_initmem();
mark_readonly();
/*
* Kernel mappings are now finalized - update the userspace page-table
* to finalize PTI.
*/
pti_finalize();
system_state = SYSTEM_RUNNING;
numa_default_policy();
rcu_end_inkernel_boot();
if (ramdisk_execute_command) {
ret = run_init_process(ramdisk_execute_command);
if (!ret)
return 0;
pr_err("Failed to execute %s (error %d)\n",
ramdisk_execute_command, ret);
}
/*
* We try each of these until one succeeds.
*
* The Bourne shell can be used instead of init if we are
* trying to recover a really broken machine.
*/
if (execute_command) {
ret = run_init_process(execute_command);
if (!ret)
return 0;
panic("Requested init %s failed (error %d).",
execute_command, ret);
}
if (!try_to_run_init_process("/sbin/init") ||
!try_to_run_init_process("/etc/init") ||
!try_to_run_init_process("/bin/init") ||
!try_to_run_init_process("/bin/sh"))
return 0;
panic("No working init found. Try passing init= option to kernel. "
"See Linux Documentation/admin-guide/init.rst for guidance.");
}
My question concerns the unused argument to the function. I have seen some other questions where one can use the GCC attribute specifier to declare the argument as unused and some other techniques, but this one looks like it would generate some weird compiler warnings since I see no usage of any suppression techniques here. Does anyone know what is the use of this argument here?

The unused parameter is there, because kernel_init is run as a kernel_thread which expects a pointer to int(void*) function as the first argument.
From here:
pid = kernel_thread(kernel_init, NULL, CLONE_FS);

Related

Warning 'return' with no value, in function returning non-void - What should it return?

How do I solve the following throwing the warning in the title?
struct Nodes* InsertNode(unsigned int IP, unsigned short Port)
{
if (!IP)
return;
if (!Port)
return;
// Above is what chucks the warnings
{
// do stuff & conditionally
return &List[x];
}
// Different conditions & stuff
{
return &List[Other];
}
}
In other words, in the case of giving up through missing data, what should it return? Or do I need to trawl through the entire body of code and have checks every time to see if it should be called or not? The program functions as intended just returning at that point, if I'm to continue using it (or upgrade the OS it's running on), fixing compiler warnings seems like a good idea, they tend to turn into errors when compiler versions get bumped.
There's a clue in this answer which answers someone asking about the same warning, the answer doesn't give me quite enough info to proceed though, nor do the other's I've read.
Extra information: The check on the values of IP & Port are there to sanitize the content of &List, such cases indicate datagrams from misconfigured clients or traffic from persons with malicious intent, sad but it happens. It's invalid data we don't care about at all, logging it seems pointless, it shouldn't delay processing the next one, and absolutely not halt the program. Until the switch from gcc 4.9 to 6.3 I didn't see a warning. The current return; appears to simply black-hole it, but I only understand bits of the code's intent.
in the case of giving up through missing data, what should it return?
As often it depends.
There are several scenarios
The function is not designed to return NULL as a valid value.
Replace
if (!IP)
return;
if (!Port)
return;
by
if (!IP || !Port)
{
errno = EINVAL; /* Setting errno, allows the caller to log
the failure using the perror() function. */
return NULL;
}
Use it like this:
struct Nodes * p = InsertNode (...);
if (NULL == p)
{
perror("InsertNode() failed");
/* exit or error logging/handling */
}
IP and Port will never be 0 under normal operation. So if they were it would be a programming mistake.
In those cases you probably no don't return but end the program.
So instead of
if (!IP)
return;
if (!Port)
return;
use
assert((IP) && (Port));
No specific usage necessary here as the program would simply end if the assertion isn't met.
Please note that this approach requires extensive testing as the test will typically be removed in a production/release build!
The function may return NULL as valid value and IP and/or Port may be 0 under normal operation.
Redesign the function to in one way or the other return a separate error status.
This can generally be done in two ways:
Use the function's return value and pass back the result via a pointer being passed as parameter
int InsertNode(unsigned int IP, unsigned short Port, struct Nodes** ppresult)
{
int error_state = 0;
if (!IP || !Port || !ppresult)
{
errno = EINVAL; /* Setting errno, allows the caller to log
the failure using the perror() function. */
error_state = -1;
}
else
{
if (...)
{
*ppresult = &List[x];
}
...
}
return error_state;
}
Use it like this:
struct Nodes * p;
if (-1 == InsertNode (..., &p))
{
perror("InsertNode() failed");
/* exit or error logging/handling */
}
Pass back the error state result via a pointer being passed as parameter
struct Nodes * InsertNode(unsigned int IP, unsigned short Port, int * perror_state)
{
int error_state = 0;
if (!IP || !Port || !perror_state)
{
errno = EINVAL; /* Setting errno, allows the caller to log
the failure using the perror() function. */
error_state = -1;
}
else
{
if (...)
{
*ppresult = &List[x];
}
...
}
*perror_state = error_state;
return NULL;
}
Use it like this:
int result;
struct Nodes * p = InsertNode (..., &result))
if (-1 == result)
{
perror("InsertNode() failed");
/* exit or error logging/handling */
}
TLDR
"Until the switch from gcc 4.9 to 6.3 I didn't see a warning." Try compiling with gcc -std=gnu90 to compile under similar conditions to those that worked before, when you were using gcc 4.9.
OK, I'm Listening
The reason that you see compiler warnings after changing compilers from gcc 4.9 to gcc 6.3 is that gcc 4.9 defaulted to C90 (really the gnu90 dialect of C90), but by gcc 5.5 the default was C11 (really gnu11).
The C90 Standard says in the Constraints section about the return statement that (C90 §6.6.6.4):
A return statement with an expression shall not appear in a function whose return type is void.
But the same Constraints section from the C11 Standard saysC11 §6.8.6.4:
A return statement with an expression shall not appear in a function whose return type is void. A return statement without an expression shall only appear in a function whose return type is void.
Now, the compiler must produce a diagnostic message for any constraint violation (§5.1.1.3). No constraint was violated when your code was compiled under C90, but the change to a more recent compiler means that the code now compiles under C11, where there is a constraint violation, hence the warning.
One option would be to simply compile with gcc -std=gnu90, allowing the code to be compiled using the same dialect of C you used before, even on the more recent compilers.
But, also note that the original code may have had undefined behavior, since (C90 §6.6.6.4):
If a return statement with an expression is executed, and the value of the function call is used by the caller, the behavior is undefined.
If the value returned by InsertNode() is used by the caller, and the return; statement is encountered in the function call, you have undefined behavior. The best choice would be to look at all of the calls to InsertNode() to see how they handle the return values. It is possible that return; is a typo, and that the code already handles returned null pointers, in which case changing to return NULL; would be all that is needed to fix the code. If the code does not already handle null pointers, #alk has provided several options for fixing the code.

How to compare my string, which is stored in an array, to function names from a complete library in c

After I enter a string in c and store it in for example char s[100], how can I compare that string to all function names in a math.h? For example, I enter pow and the result will look like this in stored form.
s[0]='p'
s[1]='o'
s[2]='w'
s[3]='\0'
Since my string is the equivalent of pow(), I want my program to recognise that and then call pow() during execution of my program. I know it is not that hard to do string comparison within the code, but that would mean that I would have to do string comparison for every function name in the library. I don't want to do that. How is it possible to compare my string against all names in the library without hard coding every comparison?
Thank you :)
You can't, not without doing work yourself. There are no names of functions present at runtime in general, and certainly not of functions you haven't called.
C is not a dynamic language, names are only used when compiling/linking.
Regular expressions in C
Try parsing the header files using FILE and use aforementioned link as a guide to check whether the function exists or not.
I tried to make a little sample about what I assume the questioner is looking for (eval.c):
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <assert.h>
/* mapping function names to function pointers and number of parameters */
struct Entry {
const char *name; /* function name */
double (*pFunc)(); /* function pointer */
int nArgs; /* number of arguments */
} table[] = {
#define REGISTER(FUNC, N_ARGS) { #FUNC, &FUNC, N_ARGS }
REGISTER(atan2, 2),
REGISTER(pow, 2),
REGISTER(modf, 2),
REGISTER(sin, 1),
REGISTER(cos, 1)
#undef REGISTER
};
/* let compiler count the number of entries */
enum { sizeTable = sizeof table / sizeof *table };
void printUsage(const char *argv0)
{
int i;
printf(
"Usage:\n"
" %s FUNC\n"
" where FUNC must be one of:\n", argv0);
for (i = 0; i < sizeTable; ++i) printf(" - %s\n", table[i].name);
}
int main(int argc, char **argv)
{
int i;
char *func;
struct Entry *pEntry;
/* read command line argument */
if (argc <= 1) {
fprintf(stderr, "ERROR: Missing function argument!\n");
printUsage(argv[0]);
return -1;
}
func = argv[1];
/* find function by name */
for (i = 0; i < sizeTable && strcmp(func, table[i].name) != 0; ++i);
if (i >= sizeTable) {
fprintf(stderr, "ERROR! Unknown function '%s'!\n", func);
printUsage(argv[0]);
return -1;
}
/* perform found function on all (standard) input */
pEntry = table + i;
for (;;) { /* endless loop (bail out at EOF or error) */
switch (pEntry->nArgs) {
case 1: {
double arg1, result;
/* get one argument */
if (scanf("%lf", &arg1) != 1) {
int error;
if (error = !feof(stdin)) fprintf(stderr, "Input ERROR!\n");
return error; /* bail out at EOF or error */
}
/* compute */
result = (*pEntry->pFunc)(arg1);
/* output */
printf("%s(%f): %f\n", pEntry->name, arg1, result);
} break;
case 2: {
double arg1, arg2, result;
/* get two arguments */
if (scanf("%lf %lf", &arg1, &arg2) != 2) {
int error;
if (error = !feof(stdin)) fprintf(stderr, "Input ERROR!\n");
return error; /* bail out at EOF or error */
}
/* compute */
result = (*pEntry->pFunc)(arg1, arg2);
/* output */
printf("%s(%f, %f): %f\n", pEntry->name, arg1, arg2, result);
} break;
default: /* should never happen */
fprintf(stderr,
"ERROR! Functions with %d arguments not yet implemented!\n",
pEntry->nArgs);
assert(0);
return -1; /* bail out at error */
}
}
}
I compiled and tested this with gcc in cygwin on Windows (64 bit):
$ gcc -std=c11 -o eval eval.c
$ ./eval
ERROR: Missing function argument!
Usage:
./eval FUNC
where FUNC must be one of:
- atan2
- pow
- modf
- sin
- cos
$ echo "1 2 3 4 5 6 7 8 9 10" | ./eval pow
pow(1.000000, 2.000000): 1.000000
pow(3.000000, 4.000000): 81.000000
pow(5.000000, 6.000000): 15625.000000
pow(7.000000, 8.000000): 5764801.000000
pow(9.000000, 10.000000): 3486784401.000000
$ echo "1 2 3 4 5 6 7 8 9 10" | ./eval sin
sin(1.000000): 0.841471
sin(2.000000): 0.909297
sin(3.000000): 0.141120
sin(4.000000): -0.756802
sin(5.000000): -0.958924
sin(6.000000): -0.279415
sin(7.000000): 0.656987
sin(8.000000): 0.989358
sin(9.000000): 0.412118
sin(10.000000): -0.544021
The usage of this application: the name of the function to apply is provided as command line argument. The values (to apply function to) are provided via standard input. In the sample session, I used echo and a pipe (|) to redirect the output of echo to the input of eval. (If eval is called stand-alone the numbers may be typed in by keyboard.)
Notes:
The table does the actual mapping of strings to function pointers. To solve that issue about the number of parameters, I considered this in struct Entry also.
The REGISTER macro is a trick to use the identifier as string constant also. The #FUNC is a stringize macro-operation (a typical C trick to prevent errors due to typos).
The sizeTable is another trick to prevent redundant definitions. I let the compiler count the number of entries. Thus, new entries may be added and it still will work without any other editing.
The actual trick is to provide a function pointer where the arguments are "left out". When it is called, the correct number of arguments is used and it works. (assuming, of course, the table initialization has been implemented carefully.) However, it would be a pain to do this in C++ because the functions with distinct number of arguments would need an appropriate function pointer with matching signature - horrible casts would be necessary. (Try to compile this with g++ -std=c++11 -c eval.c to see what I mean.)
For a productive solution, I would sort the entries by names (lexicographically) and apply a binary search (or even use hashing to be faster and more sophisticated). For this sample, I wanted to keep it simple.
math.h provides a lot of functions in "float flavor" also. These may not be added to this sample without additional effort. To support other than double arguments
some type info had to been added to the table entries
the type info has to be considered somehow in the switch statement of evaluation.
...not to mention functions where argument types are distinct to each other (or return type). (I cannot remember whether math.h even provides such functions.)
Btw. this will work for non-math.h functions also...

How to handle invalid passed arguments in Ansi C [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am new to C and come from a back ground of newer languages (like Java and C++) and I'm not sure how to handle runtime errors like an incorrect arguments sent to a function.
for example say I want to write a function to manipulate a string (assuming any valid int is an acceptable return value):
int foo (char s[]) {
if ( strlen(s) < 1)
// ERROR
....
....
return someInt;
}
How do I handle this scenario in Ansi C if I want the function to stop immediately? In C++ or Java I would throw an exception to be caught by the caller.
You can always use the return value :
if( /* some bad parameters */ )
return -1;
And then :
int value = foo( something );
if( value == -1 )
// error
else
// no error
Or pass an another parameters :
int foo( char s[], int* value )
{
if( /* error */ )
return 1;// error code 1
// ...
*value = something;
return 0;
}
Then when you call the function you can verify if it was executed correctly :
if( foo( "something", &result ) )
{
//ok
}
else
{
// not ok
}
Both of these method implies that the caller will verify manually if there was an error
if I want the function to stop immediately
Two things.
If you want only the function to stop execution and return to caller, use a return statement. Also, you may want to use some predefined or user-defined error codes as the failure case return value to distinguish the reason of failure from the caller.
If you want the program itself to terminate, call exit().
The standard way to do error handling in any C program is to reserve the return value of the function for an error code.
Most typically this is a custom enum type. Example:
typedef enum
{
FOO_OK,
FOO_ERR_STRLENGTH,
FOO_ERR_DIVIDE_BY_ZERO,
...
} foo_err_t;
foo_err_t foo_func (/* parameters */)
{
if (strlen(s) < 1)
{
return FOO_ERR_STRLENGTH;
}
...
return FOO_OK;
}
Then you document the function properly and state which error codes it may return, and what is causing them.
What should be done upon error is usually no business of your routines, but something that should be decided by the caller. In particular, your routines should never decide to terminate the whole program. That decision should be taken by the outer-most caller (top of the call stack), i.e from main().
If I thinking of your question right, most type errors will be caught on compilation. If you want to just return early, you can simply call return. Often times, error handling, C programers will add a goto for the error:
struct Data *
create_data ()
{
struct Data *data = malloc(sizeof(struct Data));
if (data == NULL)
goto exit;
/* do stuff with data */
exit:
return data;
}
That will return NULL if there was no memory. But you might want to exit early for another reason. So, if you need to exit the program gracefully (and free all the things you have taken), you're going to need a central exit point.
I usually have a function like
void bail (const char *fmt, ...)
{
va_list argp;
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
exit(EXIT_FAILURE);
}
It prints to STDERR and returns a non-0 exit as well. You could easily modify this to accept any data you need to free.
Your major options are:
Have the return value combine both the error status and the actual value. For example if your function only intends to return non-negative values, then you could say that negative return values indicate an error.
Return an error code (0 for success) and give the function's output via a reference parameter.
Return the function's output and give the error code via a reference parameter.
Other options include using a global (or thread-local) variable for error status (not a good idea IMHO), or returning a struct that contains both the return information and the error status.

TCL_LINK_STRING causing segmentation fault (core dumped)

I'm trying to share a variable with c and tcl, the problem is when i try to read the variable in the c thread from tcl, it causes segmentation error, i'm not sure this is the right way to do it, but it seems to work for ints. The part that is causing the segmentation fault is this line is when i try to print "Var" but i want to read the variable to do the corresponding action when the variable changes.
Here is the C code that i'm using
void mode_service(ClientData clientData) {
while(1) {
char* Var = (char *) clientData;
printf("%s\n", Var);
usleep(100000); //100ms
}
}
static int mode_thread(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
Tcl_ThreadId id;
ClientData limitData;
limitData = cdata;
id = 0;
Tcl_CreateThread(&id, mode_service, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
printf("Tcl_CreateThread id = %d\n", (int) id);
// Wait thread process, before returning to TCL prog
int i, aa;
for (i=0 ; i<100000; i++) {aa = i;}
// Return thread ID to tcl prog to allow mutex use
Tcl_SetObjResult(interp, Tcl_NewIntObj((int)id));
printf("returning\n");
return TCL_OK;
}
int DLLEXPORT Modemanager_Init(Tcl_Interp *interp){
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
if (Tcl_PkgProvide(interp, "PCIe", "1.0") == TCL_ERROR) {
return TCL_ERROR;
}
// Create global Var
int *sharedPtr=NULL;
//sharedPtr = sharedPtr = (char *) Tcl_Alloc(sizeof(char));
Tcl_LinkVar(interp, "mode", (char *) &sharedPtr, TCL_LINK_STRING);
Tcl_CreateObjCommand(interp, "mode_thread", mode_thread, sharedPtr, NULL);
return TCL_OK;
}
In the tcl code, i'm changing the variable mode whenever the user presses a button for example:
set mode "Idle"
button .startSamp -text "Sample Start" -width 9 -height 3 -background $btnColor -relief flat -state normal -command {set mode "Sampling"}
set threadId [mode_thread]
puts "Created thread $threadId, waiting"
Your code is a complete mess! You need to decide what you are doing and then do just that. In particular, you are using Tcl_LinkVar so you need to decide what sort of variable you are linking to. If you get a mismatch between the storage, the C access pattern and the declared semantic type, you'll get crashes.
Because your code is in too complicated a mess for me to figure out exactly what you want to do, I'll illustrate with less closely related examples. You'll need to figure out from them how to change things in your code to get the result you need.
Linking Integer Variables
Let's do the simple case: a global int variable (declared outside any function).
int sharedVal;
You want your C code to read that variable and get the value. Easy! Just read it as it is in scope. You also want Tcl code to be able to write to that variable. Easy! In the package initialization function, put this:
Tcl_LinkVar(interp /* == the Tcl interpreter context */,
"sharedVal" /* == the Tcl name */,
(char *) &sharedVal /* == pointer to C variable */,
TCL_LINK_INT /* == what is it! An integer */);
Note that after that (until you Tcl_UnlinkVar) whenever Tcl code reads from the Tcl variable, the current value will be fetched from the C variable and converted.
If you want that variable to be on the heap, you then do:
int *sharedValPtr = malloc(sizeof(int));
C code accesses using *sharedValPtr, and you bind to Tcl with:
Tcl_LinkVar(interp /* == the Tcl interpreter context */,
"sharedVal" /* == the Tcl name */,
(char *) sharedValPtr /* == pointer to C variable */,
TCL_LINK_INT /* == what is it! An integer */);
Linking String Variables
There's a bunch of other semantic types as well as TCL_LINK_INT (see the documentation for a list) but they all follow that pattern except for TCL_LINK_STRING. With that, you do:
char *sharedStr = NULL;
Tcl_LinkVar(interp, "sharedStr", (char *) &sharedStr, TCL_LINK_STRING);
You also need to be aware that the string will always be allocated with Tcl_Alloc (which is substantially faster than most system memory allocators for typical Tcl memory usage patterns) and not with any other memory allocator, and so will also always be deallocated with Tcl_Free. Practically, that means if you set the string from the C side, you must use Tcl_Alloc to allocate the memory.
Posting Update Notifications
The final piece to note is when you set the variable from the C side but want Tcl to notice that the change has set (e.g., because a trace has been set or because you've surfaced the value in a Tk GUI), you should do Tcl_UpdateLinkedVar to let Tcl know that a change has happened that it should pay attention to. If you never use traces (or Tk GUIs, or the vwait command) to watch the variable for updates, you can ignore this API call.
Donal's answer is correct, but I try to show you what you did with your ClientData.
To clarify: All (or almost all, Idk) Tcl functions that take a function pointer also take a parameter of type ClientData that is passed to your function when Tcl calls it.
Let's take a look at this line:
Tcl_CreateObjCommand(interp, "mode_thread", mode_thread, NULL, NULL);
// ------------------------------------------------------^^^^
You always pass NULL as ClientData to the mode_thread function.
In the mode_thread function you use the passed ClientData (NULL) to pass it as ClientData to the new Thread:
limitData = cdata;
// ...
Tcl_CreateThread(&id, mode_service, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
In the mode_service function you use the ClientData (which is still NULL) as pointer to a char array:
char* Var = (char *) clientData;
Which is a pointer to the address 0x00.
And then you tell printf to dereference this NULL pointer:
printf("%s\n", Var);
Which obviously crashes your program.

How to get function's name from function's pointer in C for Windows XP with MinGW?

I have seen this answer How to get function's name from function's pointer in C?. but this solution is for linux.
I found this http://ivbel.blogspot.fr/2012/02/how-to-get-functions-name-from.html
res = SymGetSymFromAddr64(GetCurrentProcess(), addr, &dis64, pSym);
if (!res)
{
/* TODO: call your trace function instead of printf */
printf("SymGetSymFromAddr64 fails, error=%ld\n", GetLastError());
return FALSE;
}
else
{
strcpy(symbolName, pSym->Name);
}
The full code is on the link

Resources