...
In this noncompliant code example, the char pointer p is initialized to the address of a string literal. Attempting to modify the string literal results in undefined behavior.
| Code Block | ||||
|---|---|---|---|---|
| ||||
char *p = "string literal"; p[0] = 'S'; |
...
As an array initializer, a string literal specifies the initial values of characters in an array, as well as the size of the array. (See rule STR36-C. Do not specify the bound of a character array initialized with a string literal.) This code creates a copy of the string literal in the space allocated to the character array a. The string stored in a can be safely modified.
| Code Block | ||||
|---|---|---|---|---|
| ||||
char a[] = "string literal"; a[0] = 'S'; |
...
In this noncompliant code example, a string literal is passed to the (pointer to non-const) parameter of the POSIX function mkstemp(), which then modifies the characters of the string literal.
| Code Block | ||||
|---|---|---|---|---|
| ||||
char *fname;
fname = mkstemp("/tmp/edXXXXXX");
|
...
Instead of passing a string literal, use a named array:
| Code Block | ||||
|---|---|---|---|---|
| ||||
static char fname[] = "/tmp/edXXXXXX"; mkstemp(fname); |
...
In this noncompliant example, the non-const char* result of the strrchr() function is used to modify the object pointed to by pathname. Since the pointer points to a string literal, the effects of the modification are undefined and are likely to cause a signal, such as SIGSEGV, to be generated for the process if the object is stored in read-only memory.
| Code Block | ||||
|---|---|---|---|---|
| ||||
const char* get_dirname(const char* pathname) {
char* slash;
slash = strrchr(pathname, '/');
if (slash)
*slash = '\0'; /* undefined behavior */
return pathname;
}
int main() {
puts(get_dirname(__FILE__));
return 0;
}
|
...
A compliant solution avoids modifying a const object, even if it is possible to obtain a non-const pointer to such an object by calling a standard C library function, such as strrchr(). To reduce the risk of callers of get_dirname() passing constant objects to the function, the argument is declared to be a non-const pointer. While converting a string literal to non-const char* is permitted by the language, conforming compilers could issue a diagnostic for such code. See also recommendation EXP05-C. Do not cast away a const qualification.
| Code Block | ||||
|---|---|---|---|---|
| ||||
char* get_dirname(char* pathname) {
char* slash;
slash = strrchr(pathname, '/');
if (slash)
*slash = '\0';
return pathname;
}
int main() {
char pathname[] = __FILE__;
/* calling get_dirname(__FILE__) may be diagnosed */
puts(get_dirname(pathname));
return 0;
}
|
...