简体   繁体   English

string.h包含对代码的影响

[英]string.h inclusion effect on code

I have sample code taken from Split string with delimiters in C 我有从Split字符串中取得的示例代码, 其中包含C语言中的分隔符

I found that if I comment out #include <string.h> the program builds, but crashes when I try to run it. 我发现如果我注释掉#include <string.h> ,程序会构建,但是当我尝试运行它时会崩溃。 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;
}

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. 如果代码不包含<string.h> ,则在<string.h>中原型化的程序使用的所有函数的返回类型将假定为int ,即32位。

If on a 64bit system this makes function returning pointers (which are 64bit) most probably fail miserably. 如果在64位系统上,这使得函数返回指针(64位)很可能会失败。 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". 这通常是strdup()的情况,它只返回引用内存的64位地址的32位来保存重复的“字符串”。

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. C编译器发出的警告就是它的警告。 Treat it as such. 这样对待它。

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). <string.h>头包含C标准指定的标准字符串函数的声明(并且可能取决于您的设置,一些其他非标准函数,如strdup() ,它由POSIX定义,但不由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; 从1990 ISO C标准开始,允许调用没有可见声明的函数,但编译器将对如何定义该函数做出某些假设; in particular, it will assume that it returns an int result. 特别是,它将假定它返回一个int结果。 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; 在某些系统上,调用一个返回char*的函数就像返回一个int 一样,似乎可以工作; 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). 一种可能的情况是intchar*类型具有不同的大小(例如,它们在64位系统上通常分别为32位和64位)。 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 ); 从1999年的标准来看,调用没有可见声明的函数是非法的( 违反约束 ); the "implicit int " rule was dropped. “隐式int ”规则被删除了。

What that means is that any compiler that conforms to the C99 or later standard must issue a diagnostic message. 这意味着任何符合C99或更高版本标准的编译器都必须发出诊断消息。 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. 在某些情况下,该诊断可能是一个警告,然后编译器可以继续根据C90规则编译您的程序 - 或者根据编译器开发人员选择的任何规则。

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. 如果你没有(直接或间接地)包含<stdio.h> ,你的编译器至少不会警告你调用strlen() ,你应该使用编译器支持的任何选项来提高它的警告级别。

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. 在某些情况下,您可以忽略警告,但最安全的做法是将编译器警告视为致命错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM