【问题标题】:segmentation fault on chars array [closed]字符数组上的分段错误[关闭]
【发布时间】:2017-06-19 21:18:43
【问题描述】:

我需要计算“字符串列表”中有多少个字符串。每个字符串像往常一样以 NUL 字符 ('\0') 结尾,列表以连续两个 NUL 字符结尾。

我写了一个函数,但我不断收到分段错误:

int numStrsInList(const char* strList) {
    int count = 0;
    int flag = 0;
    if(!(*strList))
        return -1;

    while (flag != 2) {
        if (!(*strList)) {
            count++;
            flag++;
        }
        else
            flag = 0;
        strList++;
    }
    return count;
}

例如:

const char* empty = "\0";
const char* one = "Hell0 \t\n\v\f\rw0r1d\0";
const char* two = "Hello\0 \t\0";
const char* simple = "Hello\0world\0!\0";

例如调用:

numStrsInList(empty)
numStrsInList(one)
numStrsInList(two)
numStrsInList(simple)

对于这个字符串,输出应该是:

0
1
2
3

【问题讨论】:

  • 你的函数本身意义有限。我们通常希望您提供minimal reproducible example。另外,不要显示带有行号的代码。
  • 第 1 到 34 行在哪里?另外:如果函数有效,count 将是 1 太多或 2 太多,因为不清楚列表如何结束。请发布显示问题的Minimal, Complete, and Verifiable example。将输入、预期输出和实际输出显示为问题中的文本
  • 你怎么知道哪个'\0'是列表中的最后一个'\0'?如果你不能明确地知道 "list" 的结尾是什么,那么你只会在列表结尾之后扯掉 Undefined Behavior" 分段错误.
  • @David C. Rankin,关于“你怎么知道哪个 '\0' 是列表中的最后一个 '\0'?”,如果上一个角色也是\0
  • @ikegami 请喝杯咖啡。

标签: c string algorithm segmentation-fault


【解决方案1】:

你的代码有几个问题......

int numStrsInList(const char* strList) {
    int count = 0;
    int flag = 0;
    if(!(*strList))      // this is not right, numStrsInList("\0") returns -1 instead of 0
        return -1;       // did you mean if (!strlist) ??

    while (flag != 2) {
        if (!(*strList)) {    // maybe using this notation if (!strlist[0]) 
            count++;          // would help in avoiding the error above
            flag++;           // c library has strlen() functions
        }                     // that are much faster and will make your code more readable
        else
            flag = 0;
        strList++;
      }
      return count;
    }

  }

比较,每个请求添加的总长度:)

int numStrsInList(const char* strList, int maxlen) 
{
   // returns the number of strings in a null terminated array of 
   // contiguous null-terminated strings.
   // maxlen is the maximum overall length of the buffer, 
   // can be 0 to defeat length checking

   const char* s;
   int result = 0;

   if (!strList) return -1;

   for (s = strlist; 
        s > (char*)1 && s[0] != 0; 
        s = (maxlen) ? (memchr(s, 0, maxlen - (s - strlist)) + 1)
                     : (s + strlen(s) + 1) )
   {
     if ((s - strlist) > maxlen) return -1;
     ++result;
   }

   return result;
}

【讨论】:

  • 如果没有总长度,您的代码可能会超出边界。
  • 是的。正如他们所说,垃圾进垃圾出。
  • 是的,现在看起来应该是这样(不过,有问题的 strlen() 仍然存在)。
  • 虽然对可读性有很大影响,但你是对的。
  • 修正了...我有没有提到...我得到了...我不应该提到的东西:)
【解决方案2】:

只需使用在标头<string.h> 中声明的标准C 函数strchr

例如

#include <stdio.h>
#include <string.h>

size_t numStrsInList(const char *s)
{
    size_t n = 0;

    if (!(s[0] == '\0' && s[1] == '\0'))
    {
        do
        {
            s = strchr(s, '\0');
            ++n;
        } while (*++s);
    }

    return n;
}

int main( void )
{
    printf("The number of substrings is %zu\n", numStrsInList("\0"));
    printf("The number of substrings is %zu\n", numStrsInList("Hell0 \t\n\v\f\rw0r1d\0")) ;
    printf("The number of substrings is %zu\n", numStrsInList("Hello\0 \t\0"));
    printf("The number of substrings is %zu\n", numStrsInList("Hello\0world\0!\0"));
}

程序输出是

The number of substrings is 0
The number of substrings is 1
The number of substrings is 2
The number of substrings is 3

不使用标准函数strchr,该函数可以通过以下方式实现

size_t numStrsInList(const char *s)
{
    size_t n = 0;

    if (!(s[0] == '\0' && s[1] == '\0'))
    {
        do
        {
            while (*s) ++s;
            ++n;
        } while (*++s);
    }

    return n;
}

考虑到例如这个字符串

"\0A\0"

包含两个子字符串:"""A"。虽然此字符串 "\0" 不包含任何子字符串。 至于你的代码那已经是这个语句了

if(!(*strList))
    return -1;

没有意义。

看来你的意思

if(!strList)
    return -1;

即指针strList不等于NULL。但是,与标准字符串函数类比,调用者检查指针是否等于NULL 会更好。

【讨论】:

  • 同样的问题。它可能会去UB。
  • @0andriy 请提供导致 UB 的有效输入示例。
  • @chux,不是很明显吗?任何超出页面大小的非空终止垃圾都将生成页面错误。根据接下来的页面,您可能会对分段错误感到惊讶。
  • @0andriy 您的示例不符合 OP 的标准“每个字符串都以 NUL 字符 ('\0') 结束,并且列表以两个 NUL 字符连续结束。”。 GIGO
  • @0andriy 那么 strlen 呢?您是否已经将您的提案发送给 C 标准委员会?:)
猜你喜欢
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
  • 2016-05-25
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 2018-10-17
  • 1970-01-01
相关资源
最近更新 更多