首页 > 解决方案 > 为什么我会在 C 中得到堆缓冲区溢出?

问题描述

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

int main(int argc, char* argv[])
{
  if (argc == 1)
    exit(EXIT_FAILURE);

  int count = 2;

  int i, j;
  for (i = 1; i < argc; i++)
  {
    for (j = 0; j < strlen(argv[i]); j++)
      count++;
  }

  printf("%d\n", count);

  char* original = malloc(sizeof(char) * count);
  printf("%p\n", original);
  char* copy = malloc(sizeof(char) * count);
  printf("%p\n", copy);
  memset(original, 0, strlen(original));
  memset(copy, 0, strlen(copy));

  strcpy(original, argv[1]);
  for (i = 2; i < argc; i++)
  {

    strcat(original, argv[i]);

  }

  int coun = 0;
  for (i = 0; i < strlen(original); i++)
  {
    if (original[i] == '(' || original[i] == '{' || original[i] == '[' ||
      original[i] == ')' || original[i] == '}' || original[i] == ']')
    {
      copy[coun] = original[i];
      coun++;
    }
  }

  printf("%s\n", original);
  printf("%s\n", copy);

  free(original);
  free(copy);
  exit(EXIT_SUCCESS);
}

我使用gcc -Wall -Werror -fsanitize=address balance.c -o balance来制作文件和./balance '(('来测试

我收到了这条消息

在此处输入图像描述

问题是什么?

这是获取 argv 内容并仅获取字符串括号的代码。

我得到它可能是错误检查,-fsanitize=address但我在我的代码上找不到任何错误,所以有人可以检查一下吗?

标签: c

解决方案


你的问题在这里:

memset(original,0,strlen(original));
memset(copy,0,strlen(copy));

original和都copy指向malloc初始化的内存。该strlen函数读取其参数指向的字节,直到找到一个值为 0 的字节。这意味着 1)您正在读取未初始化的内存,以及 2)因为内容不确定,该函数可以读取超过分配内存的末尾。这两个动作都会触发未定义的行为

您知道两个内存位置都指向count字节,因此将其传递给memset

memset(original,0,count);
memset(copy,0,count);

更好的是,使用calloc而不是malloc返回已初始化为 0 的内存:

char* original = calloc(sizeof(char), count);
char* copy = calloc(sizeof(char), count);

推荐阅读