关于字符串和字符的访谈问题

时间:2017-03-20 09:45:30

标签: c string char malloc free

我遇到了一家公司的两个问题。这两个问题让我困惑。 任何人都可以帮助解释答案的原因吗?

  1. 写下结果。

    void Test(void){
      char *str = (char *) malloc(100);
      strcpy(str, “hello”);
      free(str);
      if(str != NULL){
        strcpy(str, “world”);
        printf(str);
      }
    } 
    

    Ans:它将输出“world”

  2. 写下结果。

    char *GetMemory(void){
      char p[] = "hello world";
      return p;
    }
    
    void Test(void){
      char *str = NULL;
      str = GetMemory();
      printf(str);
    }
    

    Ans:输出未知,因为指针无效。

3 个答案:

答案 0 :(得分:9)

两者都会产生undefined behaviour

第一个是因为你在释放它之后使用指针(str)(free()在块之后没有/不能将指针设置为NULL。

第二个因为您正在使用指向另一个函数的局部变量的指针。

答案 1 :(得分:4)

两个示例都包含相同类型的错误,在生命周期结束后使用对象。

这样做会导致未定义的行为 1 。该文本使用“引用”一词,这基本上意味着访问一个对象或使用所述对象的标识符。

实际上在两个例子中导致未定义行为的原因并不是上面提到的规则 1 ,而是另一个与之密切相关的规则。指向生命周期结束的对象的指针值是不确定的 2 。读取此类值会导致未定义的行为。这两种情况都会发生这种情况。

在第一个例子中,str的生命周期在免费调用时结束。然后在if语句if(str != NULL){中使用该指针,这会导致未定义的行为。

在第二个例子中,当函数返回时,p的生命周期结束。返回的指针被分配给指针str:str = GetMemory();,这会导致未定义的行为。

1 (引自:ISO / IEC 9899:201x 6.2.4对象2的存储持续时间)
如果一个对象被引用到它之外 一生,行为未定义。

2 (引自:ISO / IEC 9899:201x 6.2.4对象2的存储持续时间)
当指针变为不确定时,指针的值变得不确定 它指向(或刚刚过去)的对象到达其生命周期的末尾。

答案 2 :(得分:1)

这两个例子都是"未定义行为的经典案例"。在第一种情况下,在释放它之后,您正在使用malloc的内存。在第二种情况下,您将返回一个指向其内存位于堆栈中的字符串的指针 - 一旦执行GetMemory中的返回,该指针将不再有效。

然而,"未定义的行为"意味着编译器可以做任何喜欢的事情,两种情况下的实际情况是编译器很可能只是让你重用内存。

在第一种情况下,当你释放内存时,通常发生的是块被放在一个空闲列表中以便以后重用。您可以strcpy找到它,但可能会损坏malloc的免费列表。但除非malloc尝试分配新内存,否则这无关紧要。此外,无论你strcpy,除非malloc将内存重新分配给其他地方,否则它将保持不变。这就是为什么对于某些实现(可能是大多数实现),第一个示例确实打印了#34; world"。但是,如果此函数是较大程序的一部分,则稍后可能会出现无法解释的崩溃。

在第二种情况下,来自字符串的内存是从堆栈中分配的。在这种情况下,printf需要堆栈空间,因此很可能会覆盖包含字符串字符的内存。 printf可能会打印一个垃圾字符串,但由于您将它作为第一个参数传递,它会尝试替换它在垃圾字符串中找到的任何格式说明符。所以你可能会得到垃圾,或者你可能会崩溃。