使用指针

时间:2016-01-25 08:31:30

标签: c++ c initialization malloc

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

#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;
}

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

6 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:3)

malloc()返回的指针不能保证为0 - 已填充,(或,根据任何值初始化为任何值)。除了s1[0] = '\0';部分之外,while(*s++);可能没有按照您的期望行事。

没有初始归零部分,while(*s++);无法阻止先读后读方案。

因为

undefined behavior
  1. 读取单位化内存位置(不确定值)
  2. 越过分配的内存,寻找终止null。
  3. 在这种情况下,正如彼得先生在评论中指出的那样,第一点本身会导致UB,并且无法保证它达到到第二点。但是,在某些其他情况下,即使内存已初始化但未以空终止,您也会点击第二个点来调用UB。

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

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

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

为:

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

您的程序将会运行。

答案 4 :(得分:0)

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

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

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

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

答案 5 :(得分:-1)

声明

while(*s++);  

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

你需要知道传递的第一个参数是否为空字符串

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