【问题标题】:Understanding malloc with char pointers and strcpy用 char 指针和 strcpy 理解 malloc
【发布时间】:2020-09-30 09:38:04
【问题描述】:

我想编写一个简单的程序,我希望它无法理解 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;
}

【问题讨论】:

  • “我希望它无法理解 strcpy 和正确的内存管理,但它仍然执行”嗯...?

标签: c pointers malloc strcpy


【解决方案1】:

越界写入数组的行为是未定义的。在我的电脑上,没有优化:

% 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 检查目标缓冲区的长度,如果超过,程序将在运行时中止

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

【讨论】:

    【解决方案2】:

    这里的错误是你依赖undefined behaviour

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

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

    来自man page

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

    【讨论】:

    • 哦,我明白了。所以这段代码正在做我想做的事情并且没有正确分配内存但仍在执行?
    • @Onederfoo 是的。未定义的行为包括“显然工作正常”
    猜你喜欢
    • 2014-10-19
    • 2016-09-29
    • 1970-01-01
    • 2014-11-06
    • 2017-03-30
    • 1970-01-01
    • 2021-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多