c - 调用 strcpy 后尝试释放内存导致程序崩溃

标签 c microcontroller lpc

我知道这里有很多人提示 strcpy,但我没有通过搜索找到任何可以解决我遇到的问题的东西。

首先,调用 strcpy 本身不会导致任何类型的崩溃/段错误。其次,代码包含在一个函数中,我第一次调用这个函数时它运行得很好。它只会在第二次通过时崩溃。

我正在使用 LPC1788 微 Controller 进行编程;内存非常有限,所以我明白为什么像 malloc 这样的东西可能会失败,但不是免费的。

函数 trimMessage() 包含代码,该函数的目的是在大型字符串数组变得太大时删除一部分。

void trimMessage()
{
  int trimIndex;
  // currMessage is a globally declared char array that has already been malloc'd
  // and written to.
  size_t msgSize = strlen(currMessage);

  // Iterate through the array and find the first newline character. Everything
  // from the start of the array to this character represents the oldest 'message'
  // in the array, to be got rid of.
  for(int i=0; i < msgSize; i++)
  {
    if(currMessage[i] == '\n')
    {
      trimIndex = i;
      break;
    }
  }
  // e.g.: "\fProgram started\r\nHow are you?\r".
  char *trimMessage = (char*)malloc((msgSize - trimIndex - 1) * sizeof(char));

  trimMessage[0] = '\f';

  // trimTimes = the number of times this function has been called and fully executed.
  // freeing memory just below is non-sensical, but it works without crashing.
  //if(trimTimes == 1) { printf("This was called!\n"); free(trimMessage); }
  strcpy(&trimMessage[1], &currMessage[trimIndex+1]);

  // The following line will cause the program to crash. 
  if(trimTimes == 1) free(trimMessage);
  printf("trimMessage: >%s<\n", trimMessage);

  // Frees up the memory allocated to currMessage from last iteration
  // before assigning new memory.
  free(currMessage);
  currMessage = malloc((msgSize - trimIndex + 1) * sizeof(char));

  for(int i=0; i < msgSize - trimIndex; i++)
  {
    currMessage[i] = trimMessage[i];
  }

  currMessage[msgSize - trimIndex] = '\0';
  free(trimMessage);
  trimMessage = NULL;

  messageCount--;
  trimTimes++;
}

感谢所有提供帮助的人。该功能现在可以正常工作。对于那些问我为什么要打印我刚刚释放的数组的人,那只是为了表明问题发生在 strcpy 之后,并排除了它之后出现的任何其他代码。

最后的代码在这里,以防它对遇到类似问题的任何人有用:

void trimMessage()
{
  int trimIndex;
  size_t msgSize = strlen(currMessage);

  char *newline = strchr(currMessage, '\n'); 
  if (!newline) return;
  trimIndex = newline - currMessage;

  // e.g.: "\fProgram started\r\nHow are you?\r".
  char *trimMessage = malloc(msgSize - trimIndex + 1);

  trimMessage[0] = '\f';
  strcpy(&trimMessage[1], &currMessage[trimIndex+1]);

  trimMessage[msgSize - trimIndex] = '\0';

  // Frees up the memory allocated to currMessage from last iteration
  // before assigning new memory.
  free(currMessage);
  currMessage = malloc(msgSize - trimIndex + 1);

  for(int i=0; i < msgSize - trimIndex; i++)
  {
    currMessage[i] = trimMessage[i];
  }

  currMessage[msgSize - trimIndex] = '\0';
  free(trimMessage);

  messageCount--;
}

最佳答案

如果堆已损坏或向其传递无效指针,free 可能并且将会崩溃。

看着那个,我认为你的第一个 malloc 是几个字节短。您需要为空终止符保留一个字节,并且您正在复制到偏移量 1,因此您需要为此保留另一个字节。因此,将要发生的是您的副本将覆盖下一个堆 block 开始处的信息(通常用于下一个堆 block 的长度以及是否使用它的指示,但这取决于您的 RTL ).

当您下次执行空闲操作时,它很可能会尝试合并任何空闲 block 。不幸的是,您已经损坏了下一个 block 的 header ,此时它会变得有点疯狂。

关于c - 调用 strcpy 后尝试释放内存导致程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12217644/

相关文章:

c++ - 无法从 raspberry pi pico ( c sdk ) 发送串行数据

c - 尽管包含 'strnlen',但未定义对 "string.h"的引用

c - RTOS 数据记录器示例

c - LPC微 Controller 上的IAP

c - 打印链表

C : converting binary to decimal

c - 为什么我会出现段错误?

iphone - 标签中显示的格式字符串

c - 将汇编语言翻译成 C [使用 PIC18 写入内存]

python - 微 Controller 和pyserial之间的双向通信