使用char指针和strcpy理解malloc

使用char指针和strcpy理解malloc,c,pointers,malloc,strcpy,C,Pointers,Malloc,Strcpy,我想写一个简单的程序,我希望它不能理解strcpy和适当的内存管理,但它仍然执行。我正在尝试为一个字符串动态分配内存(使用malloc),该字符串只够用作目标的3个字符(或小于源字符的任何字符),并且分配的内存(或字符)少于堆栈上分配的源字符串数组(10个字符的字符串)。无论我如何定义内存分配,它都会复制和打印内容。这里怎么了 #include <stdio.h> #include <string.h> #include <stdlib.h> int mai

我想写一个简单的程序,我希望它不能理解strcpy和适当的内存管理,但它仍然执行。我正在尝试为一个字符串动态分配内存(使用malloc),该字符串只够用作目标的3个字符(或小于源字符的任何字符),并且分配的内存(或字符)少于堆栈上分配的源字符串数组(10个字符的字符串)。无论我如何定义内存分配,它都会复制和打印内容。这里怎么了

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

int main()
{
    char *ch = NULL;
    char name[10] = "something";
    ch = (char*)malloc(3 * sizeof(char));
    strcpy(ch, name);
    
    printf("%s\n", name);
    free(ch);
    ch = NULL;
}
#包括
#包括
#包括
int main()
{
char*ch=NULL;
字符名[10]=“某物”;
ch=(char*)malloc(3*sizeof(char));
strcpy(ch,name);
printf(“%s\n”,名称);
免费(ch);
ch=NULL;
}

这里的错误是你所依赖的

编译器不会为超出限制(或无效)的内存访问抛出任何错误,但当您的程序尝试访问无效内存时,行为是未定义的

对于
strcpy()
,如果目标缓冲区不够大,无法容纳来自源的内容,包括空终止符,那么实际上您将访问超出限制的内存,这是无效的,导致未定义的行为。程序员有责任确保目标缓冲区有足够的空间来存储要复制的字符串

strcpy()
函数将
src
指向的字符串(包括终止的空字节(
'\0'
)复制到
dest
指向的缓冲区。字符串不能重叠,目标字符串
dest
必须足够大才能接收副本。[….]


将数组写出界的行为未定义。在我的计算机上,无需优化:

% gcc overflow.c
% ./a.out    
something
并且启用了优化

% gcc -O3 overflow.c
In file included from /usr/include/string.h:495,
                 from overflow.c:2:
In function ‘strcpy’,
    inlined from ‘main’ at overflow.c:10:5:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:90:10: warning: 
     ‘__builtin___memcpy_chk’ writing 10 bytes into a region of size 3
     overflows the destination [-Wstringop-overflow=]
   90 |   return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% ./a.out       
*** buffer overflow detected ***: terminated
[2]    240741 abort (core dumped)  ./a.out
原因是,通过优化,GCC将实际传播数组大小,并生成与

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

int main(void)
{
    char name[10] = "something";
    char *ch = malloc(3);
    __memcpy_chk(ch, name, sizeof name, 3);
    puts(name);
    free(ch);
}
#包括
#包括
#包括
内部主(空)
{
字符名[10]=“某物”;
char*ch=malloc(3);
__memcpy_chk(ch,name,sizeof name,3);
(姓名);
免费(ch);
}
并且检查目标缓冲区的长度,由于超出了该长度,程序将在运行时中止


始终在开发时,请记住测试您的代码是否也启用了优化

哦,我明白了。所以这段代码正在做我想要的事情,并且没有正确分配内存,但仍然在执行?@Onederfoo是的。未定义的bahaviour包括“显然工作正常”“我希望它不能理解strcpy和正确的内存管理,但它仍然执行“嗯…?”。。。?