字符串的数组内存分配

时间:2015-06-09 11:21:05

标签: c string undefined-behavior buffer-overflow gets

我使用数组分配方法编写了简单的字符串程序。我已经分配了10个字符的字符数组,但是当我输入时,程序正在接受大于10个字节的输入字符串。只有当我提供大约21个字符的输入字符串时,才会出现分段错误。当我的输入超出分配的数组限制时,为什么没有分段错误?

程序:

    private void BtnEmail_Click(object sender, RoutedEventArgs e)
    {
        string richText = new TextRange(txtEmail.Document.ContentStart, txtEmail.Document.ContentEnd).Text;
        richText = Regex.Replace(richText, @"(\n|\r)", "", RegexOptions.Multiline);
        richText = Regex.Replace(richText, @"( ;|; )", ";", RegexOptions.Multiline);
        txterrormessage.Visibility = System.Windows.Visibility.Hidden;

        if (!Regex.IsMatch(richText, @"^[\W]*([\w+\-.%]+@[\w\-.]+\.[A-Za-z]{2,4}[\W]*,{1}[\W]*)*([\w+\-.%]+@[\w\-.]+\.[A-Za-z]{2,4})[\W]*$"))
        {
            string[] emails = Regex.Split(richText, ";", RegexOptions.Multiline);
            foreach (string item in emails)
            {
                if (string.IsNullOrEmpty(item))
                    continue;

                if (!Regex.IsMatch(item, @"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"))
                {
                    txterrormessage.Text = item + " is not a valid email address";
                    txterrormessage.Visibility = System.Windows.Visibility.Visible;
                    break;
                }
            }
            if (string.IsNullOrEmpty(txterrormessage.Text))
            {
                txterrormessage.Text = "Separate emails with ; ";
                txterrormessage.Visibility = System.Windows.Visibility.Visible;
            }
        }
    }

输出:

  

输入字符串:n durga prasad

     

string = n durga prasad的值   字符串长度= 14

如您所见,字符串长度显示为14,但我只分配了10个字节。长度怎么能超过我分配的大小?

4 个答案:

答案 0 :(得分:0)

请不要使用gets()它会遇到缓冲区溢出问题,而缓冲区溢出问题会调用undefined behaviour

  

当我的输入超出分配的数组限制时,为什么没有分段错误?

一旦输入超出分配的数组大小(,即9个有效字符+ 1个空终结符),则数组位置的下一次访问将成为非法并调用UB。分段错误是 UB的副作用之一, 必须

解决方案:改为使用fgets()

答案 1 :(得分:0)

当您输入的数字超过数组可容纳的字符数时,您就会有未定义的行为。你的数组可以包含9个字符后跟一个空终止符,因此任何一个UB都是UB。

请勿使用gets()使用fgets()代替

char a[10];
fgets(a,sizeof(a),stdin);

通过使用fgets(),您可以避免缓冲区溢出问题并避免未定义的行为。

PS:fgets()附带换行符

答案 2 :(得分:0)

当您声明一个数组(如char str[10];)时,您的编译器并不总是精确地分配您需要的字节数。如果您使用64位系统,它通常会分配更多,通常为8的倍数,例如在您的情况下可能为16。

所以即使你要求10个字节,你也可以操作更多。但是,当然,这是强烈推荐的,因为正如你所说,它会产生分段错误。

而且,如Sourav和Gopi的其他答案所述,使用fgets代替gets也可能有助于减少不明确的行为。

答案 3 :(得分:0)

正如您所知,您的输入导致缓冲区溢出,我不会重复原因。相反,我想回答这个问题,

  • "当我的输入超出分配的数组限制时,为什么没有分段错误?"

可能存在或可能不存在分段错误的原因取决于undefined behaviour。一旦超出分配的内存边界,您就不应该出现 的分段错误。相反,你要面对的是UB(如前所述)。现在,引用UB的结果,

  

[...]调用未定义行为的程序可能会编译和运行,并产生正确的结果,或不可检测的错误结果或任何其他行为。

因此,在访问下一个内存时,您必须立即立即获取分段错误。它可能运行得非常好,除非它到达某个特定进程实际上无法访问的内存,然后SIGSEV信号(11)将被提升。

但是,在运行到UB之后,任何后续语句的任何输出都不能验证。因此,此处strlen()的输出无效。