使用 char 指针和 strcpy 理解 malloc
Understanding malloc with char pointers and strcpy
我想写一个简单的程序,我希望它不能理解 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;
}
这里的错误是你依赖 undefined behaviour。
编译器不会为 out-of-bound(或无效)内存访问抛出任何错误,但是当您的程序尝试访问无效内存时,行为是未定义的。
对于 strcpy()
,如果目标缓冲区不够大,无法容纳来自源的内容,包括 null-terminator,那么基本上您将越界访问内存,这无效,导致未定义的行为。程序员有责任确保目标缓冲区有足够的 space 来存储要复制的字符串。
来自man page
The strcpy()
function copies the string pointed to by src
, including the terminating null byte ('[=13=]'
), to the buffer pointed to by dest
. The strings may not overlap, and the destination string dest
must be large enough to receive the copy.[....]
数组越界写入行为未定义。在我的电脑上,没有优化:
% 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
原因是 with 优化 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);
}
和__memcpy_chk
将检查目标缓冲区的长度,并且由于超出了长度,程序将中止在运行时。
始终在开发时,记得测试您的代码优化也已启用!
我想写一个简单的程序,我希望它不能理解 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;
}
这里的错误是你依赖 undefined behaviour。
编译器不会为 out-of-bound(或无效)内存访问抛出任何错误,但是当您的程序尝试访问无效内存时,行为是未定义的。
对于 strcpy()
,如果目标缓冲区不够大,无法容纳来自源的内容,包括 null-terminator,那么基本上您将越界访问内存,这无效,导致未定义的行为。程序员有责任确保目标缓冲区有足够的 space 来存储要复制的字符串。
来自man page
The
strcpy()
function copies the string pointed to bysrc
, including the terminating null byte ('[=13=]'
), to the buffer pointed to bydest
. The strings may not overlap, and the destination stringdest
must be large enough to receive the copy.[....]
数组越界写入行为未定义。在我的电脑上,没有优化:
% 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
原因是 with 优化 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);
}
和__memcpy_chk
将检查目标缓冲区的长度,并且由于超出了长度,程序将中止在运行时。
始终在开发时,记得测试您的代码优化也已启用!