繁体   English   中英

strcat实现使用指针

[英]strcat implementation using pointers

有人知道,当我这样写时,程序崩溃了。

#include<stdio.h>
#include<stdlib.h>

void mystrcat(char *s,char *t) {
    while(*s++);
    s--;
    while(*s++ = *t++);
}

int main(void) {
    int size = 1024;
    char *s1, *s2;

    s1 = (char *)malloc(size);
    //s1[0] = '\0';   ********NOTE THIS********
    s2 = (char *)malloc(size);
    //s2[0] = '\0';   ********NOTE THIS********
    mystrcat( s1, "Hello " );
    mystrcat( s2, "World" );
    mystrcat( s1, s2 );
    printf( "\"%s\"\n", s1 );
    return 0;
}

但奇怪的是,当我不使用这两个“//”评论时,它有效! 那么为什么要添加那些简单的s2[0] = '\\0'; 可以使这个程序工作。

当您通过旧的C malloc函数或C ++ new运算符分配内存时,该内存不会以任何方式初始化。 在初始化时读取该内存会导致未定义的行为 ,并且未定义的行为(或UB因为它经常被缩短)是崩溃的主要原因之一。

malloc()返回的指针不保证是0填充的( 或者,就此而言,根据任何值初始化为任何值 )。 除了s1[0] = '\\0'; part, while(*s++); 可能没有做你期望的事情。

没有初始归零部分, while(*s++); 无法阻止read-before-write场景。

由于这是未定义的行为

  1. 读取单位化内存位置(不确定值)
  2. 经过分配的内存,寻找终止null。

在这种情况下,正如彼得先生在评论中指出的那样,第一点本身会导致UB,并且无法保证它将达到第二点。 但是,在某些其他情况下,即使内存已初始化但未终止,也会触及第二个点来调用UB。

在C中,每个字符串都以'\\ 0'字符终止。
malloc只是分配内存,它不会为你写'\\ 0'。
如果您不添加它,程序将不知道字符串的结尾在哪里,并且可能会尝试在实际字符串之后读取一些未分配的内存,因此它将导致未定义的行为。

实际上, mystrcat函数会使指针递增,直到它指向'\\ 0'字符或0
但是如果在分配的内存中找不到0,那么在指针的下一个增量之后,它将指向一些未分配的内存。
现在取消引用它将导致未定义的行为。

正如其他答案所说,你需要初始化那个内存。 你可以通过多种方式实现这一点,但一种方法是使用calloc而不是malloc。 如果你改变这两行:

s1 = (char *)malloc(size);    
s2 = (char *)malloc(size);

至:

s1 = calloc(size,sizeof(*s1));   
s2 = calloc(size,sizeof(*s2));

你的程序将运行。

当你调用malloc ,你会收到你的char*到某些内存。 你拥有该内存的size字节。 但是malloc并没有以任何方式准备你现在拥有的内存。 它保留在先前拥有的进程留在其中的任何状态。因此,很可能是您收到的内存已包含长度超过size的字符串。

因此,当您开始strcat并运行到第一个字符串的末尾时,它将超过size的长度,并尝试开始写入此内存。 这里出现了问题,因为你没有在那个位置拥有内存,因此程序会出现段错误。

另一方面,如果通过让第一个字节为"\\0"来初始化字符串,则实际上将字符串的长度设置为0(因为在结束标记之前有0个字节: "\\0" )。 因此,当你开始你的strcat ,它将再次运行到第一个字符串的末尾,但这次结束是在size范围内。

请注意,如果组合字符串长度超过size您可能仍会遇到问题。

该声明

while(*s++);  

mystrcat前两次调用没有任何意义,并调用未定义的行为。 你不应该读取未初始化的内存。

您需要检查传递的第一个参数是否为空字符串

void mystrcat(char *s,char *t) {
    if(strlen(s))
    {
        while(*s++);
        s--;
    }
    while(*s++ = *t++);
}

暂无
暂无

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

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