execl 컴파일 시 경고:warning: not enough variable arguments to fit a sentinel 설명 (전재)

GCC 4 warnings about sentinels


Introduction


When compiling something with GCC 4, it may be possible that you get one of the following warnings:
warning: missing sentinel in function call warning: not enough variable arguments to fit a sentinel
This document explains what these warnings mean and how to resolve them.

Sentinels & warnings


A sentinel is a special value which indicates the end of a series of data. In the context of GCC, it is a null pointer which ends a list of parameters to a function.
The function
execl(const char * path, const char * arg, ...)
  takes a variable amount of parameters. To know where to stop reading parameters, the last parameter must be a null pointer. When you do not end the list with a null pointer, execl will not stop scanning, which will result in errors. The following code, therefore, is wrong:
 
#include <unistd.h>

int main() {
	execl("/bin/ls", "ls", "-l");
	return 0;
}

The execl function call is not terminated by a null pointer and GCC will give a warning. The following code is better:
#include <unistd.h>

int main() {
	execl("/bin/ls", "ls", "-l", NULL);
	return 0;
}

As you can see, the execl function is now terminated by a null pointer and it will stop scanning it's arguments after that. However, GCC 4 will still issue a warning: warning: missing sentinel in function call This is because NULL is not of the right type: it is defined as integer 0 instead of a pointer with the value 0. Doing an explicit cast can make the warning go away:
#include <unistd.h>

int main() {
	execl("/bin/ls", "ls", "-l", (char *)NULL);
	return 0;
}

Using sentinels


One can specify that a function uses a sentinel by declaring it as follows:
char * build_path(const char * str, ...) __attribute__((__sentinel__(0)));

This indicates that the parameter list is ended with the special value 0, which must be a char pointer.
On most systems, there is no difference between 0 and (char *)0. On 64 bit systems, however, the integer 0 is 32 bits and the pointer 0 is 64 bits. The compiler does not know whether it is an integer or a pointer, and defaults for the integer. This will not clear the upper 32 bits and the function will not stop scanning its parameters.
home | home
© Sjoerd Langkemper

좋은 웹페이지 즐겨찾기