【问题标题】:C string from GetString() when strlen produces segmentation fault [closed]当strlen产生分段错误时来自GetString()的C字符串[关闭]
【发布时间】:2013-04-09 01:53:10
【问题描述】:

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

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

我相信这与 strlen 有关。

我使用 strlen 的唯一一次是:

    string s = GetString();

    int stringlength = strlen(s);

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

我的代码有什么问题?

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] = '\0';

    // return string
    return minimal;
}

【问题讨论】:

  • GetString 是做什么的?我猜你没有空终止你的字符串......
  • 什么是stringstd::stringchar *?
  • @LeeTaylor 我假设它返回一个 C 字符串。那么,您的问题是 string 是 C++ 类型,而 strlen 需要一个以 null 结尾的字符数组。
  • 这是 C 还是 C++?如果是 C,那么string 是如何定义的?如果是 C++,是 std::string,还是别的什么?如果是std::stringstrlen(s) 怎么编译?更重要的是,GetString 究竟返回了什么?
  • @IberoMedia:您的学校是否为您提供了有关 GetString 所做工作的文档?特别是,在某些情况下它可以返回NULL 或其他一些无效字符串? (string 不是标准的 C 类型,但我猜stringchar* 的别名,否则对strlen 的调用将无法编译)。事实上,我认为这个问题不能在这里回答。尝试使用调试器查找更高的回溯,并检查所有正在使用的指针的值。

标签: c string segmentation-fault strlen cs50


【解决方案1】:

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

如果你不检查就将返回值传递给strlen(),你的程序将会崩溃。

string s = GetString();
int stringlength = 0;

if (s != 0)
    stringlength = strlen(s);

这至少不会崩溃。

您可能还会注意到typedef char *string; 造成的混乱程度以及它带来的益处微乎其微,并将其铭记于心。你不必重复那些教你的人的错误。

我还观察到代码片段:

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

可能会更好,更简单,写成:

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

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

【讨论】:

  • 谢谢,在我使用 strlen 之前检查字符串是否为 null 解决了我的问题。谢谢
猜你喜欢
  • 1970-01-01
  • 2021-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-25
  • 2020-07-15
相关资源
最近更新 更多