Reputation: 18175
I have sample code taken from Split string with delimiters in C
I found that if I comment out #include <string.h>
the program builds, but crashes when I try to run it. Why does it crash?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
char** str_split(char* a_str, const char a_delim)
{
char** result = 0;
size_t count = 0;
char* tmp = a_str;
char* last_comma = 0;
char delim[2];
delim[0] = a_delim;
delim[1] = 0;
/* Count how many elements will be extracted. */
while (*tmp)
{
if (a_delim == *tmp)
{
count++;
last_comma = tmp;
}
tmp++;
}
/* Add space for trailing token. */
count += last_comma < (a_str + strlen(a_str) - 1);
/* Add space for terminating null string so caller
knows where the list of returned strings ends. */
count++;
result = malloc(sizeof(char*) * count);
if (result)
{
size_t idx = 0;
char* token = strtok(a_str, delim);
while (token)
{
assert(idx < count);
*(result + idx++) = strdup(token);
token = strtok(0, delim);
}
assert(idx == count - 1);
*(result + idx) = 0;
}
return result;
}
int main()
{
char months[] = "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC";
char** tokens;
printf("months=[%s]\n\n", months);
tokens = str_split(months, ',');
if (tokens)
{
int i;
for (i = 0; *(tokens + i); i++)
{
printf("month=[%s]\n", *(tokens + i));
free(*(tokens + i));
}
printf("\n");
free(tokens);
}
return 0;
}
Upvotes: 0
Views: 157
Reputation: 263177
The <string.h>
header contains the declarations of the standard string functions specified by the C standard (and possibly, depending on your settings, some additional non-standard functions like strdup()
, which is defined by POSIX but not by C).
As of the 1990 ISO C standard, calling a function with no visible declaration is permitted, but the compiler will make certain assumptions about how that function is defined; in particular, it will assume that it returns an int
result. If it's not actually defined that way, the call has undefined behavior. On some systems, calling a function that returns a char*
as if it returned an int
will appear to work; on others, it can fail in various horrible ways (which is actually better, because it makes it easier to find and correct the error).
One likely scenario is that the types int
and char*
have different sizes (for example, they're often 32 and 64 bits, respectively, on 64-bit systems). Or they might have the same size, but be returned from functions in different registers.
As of the 1999 standard, calling a function with no visible declaration is illegal (a constraint violation); the "implicit int
" rule was dropped.
What that means is that any compiler that conforms to the C99 or later standard must issue a diagnostic message. In some cases, that diagnostic can be a warning, and the compiler can then go on to compile your program under the C90 rules -- or under any rules the compiler developers happened to choose.
If your compiler doesn't at least warn you about a call to strlen()
when you haven't (directly or indirectly) included <stdio.h>
, you should use whatever options your compiler supports to increase its warning level.
You can get away with ignoring warnings in some cases, but the safest practice is to treat compiler warnings as if they were fatal errors.
Upvotes: 0
Reputation: 70883
If the code does not include <string.h>
the return types for all functions used by the program which are prototyped in <string.h>
will be assumed as int
, which is 32bit.
If on a 64bit system this makes function returning pointers (which are 64bit) most probably fail miserably. This typically will be the case for strdup()
, which would only return 32bits of a 64 address referencing the memory to hold the duplicated "string".
I clear hint for the case described above would be such a warning
warning: implicit declaration of function ‘strdup’
A warning issued by a C compiler is meant as what it is, a warning. Treat it as such.
Upvotes: 2