为什么这样做?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char * abc = malloc(1) + 4; //WRONG use of malloc.
char * xyz = "abc";
strcpy(abc, xyz); //Should fail.
printf("%sn", abc); //Prints abc
}
我预计strcpy会因为内存不足而失败,因为我将1传递给malloc()的参数。相反,它可以完美地编译和运行(在linux上的GCC和Windows上的dev c++中)。
这是意料之中的行为,还是一个愉快的巧合?
我认为这不是一个好的做法,但为什么它有效
如果没有malloc()
末尾的+4
,我会出现分段错误。这主要是我好奇的地方。
这是未定义的行为不要那样做。
您正试图访问分配区域之外的内存位置。因此,内存位置无效,访问无效内存会调用UB。
FWIW,
-
在C标准中有一点值得注意,阻止访问越界(无效)内存和
-
strcpy()
也不检查与源长度相比目的地缓冲器的大小
因此,这段代码(以某种方式)进行了编译。一旦你运行它,它就会到达UB,就再也不能保证什么了。
p.S-这里只有有保证的东西是未定义的行为
这基本上是对C中的指针是低级的并且(通常)未检查这一事实的另一个证明。你说你预计它会"因为没有足够的内存而失败",但想想看:你预计会失败什么?strcpy
函数肯定不会检查它正在复制的字符串是否有足够的空间。它没有办法这样做;它得到的只是一个指针。它只是开始复制字符,在实践中,它要么成功,要么因违反分段而死亡。(但关键是它不会在"内存不足"时死亡。)
不要依赖这种行为。"积极"回应的回答者是有道理的,因为依赖这种行为可能会潜伏多年而未被发现,然后有一天,对运行时系统的微小调整突然导致灾难性的故障。
它之所以有效,是因为自从32位计算机出现以来,许多;如果不是大多数的话;C运行库实现了malloc/free,它以16字节的粒度管理堆。也就是说,使用从1到16的参数调用malloc()
提供相同的分配。所以你得到的内存比你要求的多一点,这就允许它执行。
像valgrind
这样的工具肯定会检测到问题。