C语言 当 strlen 产生分段错误时,来自 GetString() 的 C 字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15892003/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:59:51  来源:igfitidea点击:

C string from GetString() when strlen produces segmentation fault

cstringsegmentation-faultstrlencs50

提问by IberoMedia

I am running a program in C. When I run the program I get a segmentation fault error. IN gdb when I backtrace it tells me

我正在用 C 运行一个程序。当我运行该程序时,我收到一个分段错误错误。当我回溯时,在 gdb 中它告诉我

Program received signal SIGSEGV, Segmentation fault. __strlen_sse2_bsf () at ../sysdeps/i386/i686/multiarch/strlen-sse2-bsf.S:51 51 movdqu (%edi), %xmm1

程序收到信号 SIGSEGV,分段错误。__strlen_sse2_bsf () at ../sysdeps/i386/i686/multiarch/strlen-sse2-bsf.S:51 51 movdqu (%edi), %xmm1

I believe it has to do with strlen.

我相信这与strlen有关。

The only time I use strlen is:

我唯一使用 strlen 的时间是:

    string s = GetString();

    int stringlength = strlen(s);

When I change strlen for sizeof error stops.

当我为 sizeof 更改 strlen 时,错误停止。

What is wrong with my code?

我的代码有什么问题?

Documentation of GetString

GetString 的文档

/*
 * Reads a line of text from standard input and returns it as a 
 * string (char *), sans trailing newline character.  (Ergo, if
 * user inputs only "\n", returns "" not NULL.)  Returns NULL
 * upon error or no input whatsoever (i.e., just EOF).  Leading
 * and trailing whitespace is not ignored.  Stores string on heap
 * (via malloc); memory must be freed by caller to avoid leak.
 */

string GetString(void) {
    // growable buffer for chars
    string buffer = NULL;

    // capacity of buffer
    unsigned int capacity = 0;

    // number of chars actually in buffer
    unsigned int n = 0;

    // character read or EOF
    int c;

    // iteratively get chars from standard input
    while ((c = fgetc(stdin)) != '\n' && c != EOF)
    {
        // grow buffer if necessary
        if (n + 1 > capacity)
        {
            // determine new capacity: start at 32 then double
            if (capacity == 0)
                capacity = 32;
            else if (capacity <= (UINT_MAX / 2))
                capacity *= 2;
            else
            {
                free(buffer);
                return NULL;
            }

            // extend buffer's capacity
            string temp = realloc(buffer, capacity * sizeof(char));
            if (temp == NULL)
            {
                free(buffer);
                return NULL;
            }
            buffer = temp;
        }

        // append current character to buffer
        buffer[n++] = c;
    }

    // return NULL if user provided no input
    if (n == 0 && c == EOF)
        return NULL;

    // minimize buffer
    string minimal = malloc((n + 1) * sizeof(char));
    strncpy(minimal, buffer, n);
    free(buffer);

    // terminate string
    minimal[n] = '
string s = GetString();
int stringlength = 0;

if (s != 0)
    stringlength = strlen(s);
'; // return string return minimal; }

回答by Jonathan Leffler

The description of the getString()function clearly states that it can return NULL on an error or on EOF.

getString()函数的描述清楚地表明它可以在出现错误或 EOF 时返回 NULL。

If you pass the return value to strlen()without checking, your program will crash.

如果您将返回值传递给strlen()没有检查,您的程序将崩溃。

// minimize buffer
string minimal = malloc((n + 1) * sizeof(char));
strncpy(minimal, buffer, n);
free(buffer);

This at least won't crash.

这至少不会崩溃。

You might also notice how much confusion the typedef char *string;causes and how little benefit it confers, and take it to heart. You don't have to repeat the mistakes of those who are teaching you.

您可能还会注意到typedef char *string;原因有多少混乱以及它带来的好处有多少,并将其牢记在心。你不必重复那些教你的人的错误。

I also observe that the code fragment:

我还观察到代码片段:

string minimal = realloc(buffer, n + 1);

could be better, and more simply, written as:

可以更好,更简单地写成:

##代码##

to shrink the allocation to the correct size.

将分配缩小到正确的大小。