使用 realloc() 使 memmove() 安全 [重复]

Posted

技术标签:

【中文标题】使用 realloc() 使 memmove() 安全 [重复]【英文标题】:Making memmove() safe using realloc() [duplicate] 【发布时间】:2016-04-17 07:15:06 【问题描述】:

在我的函数中替换一个子字符串。如果输入的子字符串比原来的长,它会将输入字符串的一部分移出,为输入的子字符串腾出空间。

我了解这会导致未定义的行为。我认为我应该能够使用 realloc() 分配所需的空间,但没有成功。

我尝试在 memmove() 之前添加这个:

char *newspc = (char*)realloc(in,len+sublen);
in = newspc;

这是一个合理的策略吗?为该操作腾出空间的正确方法是什么?

这是没有使用 realloc() 的程序:

#include <iostream>
#include <string>
#include <string.h>

void replc(char* in, char* subin);

int main()

  char stmt[] = "replacing this $string ok";
  std::cout << stmt << "\n";
  replc(stmt, "longerstring");  //<<<4 characters longer breaks the program
  std::cout << stmt << "\n";



void replc(char* in, char* subin)
  uint8_t len = strlen(in);
  uint8_t aftok = strchr(strchr(in, '$'), ' ')-in;
  uint8_t dollar = strchr(in, '$')-in;
  uint8_t tklen = aftok - dollar;
  uint8_t sublen = strlen(subin);

   if(sublen <= tklen)
    //enough room for substring
    memmove(in+aftok-(tklen-sublen), in+aftok, (tklen-sublen)+1);
    memcpy(in+dollar, subin, sublen);
    in[len-(tklen-sublen)] = '\0';
   
   else
   //not enough room for substring
   // memory allocation should take place here?
    memmove(in+aftok+(sublen-tklen), in+aftok, (sublen-tklen)+1);
    memcpy(in+dollar, subin, sublen);
    in[len+(sublen-tklen)] = '\0';
   


【问题讨论】:

我认为字符串之外的任何索引都是未分配的内存。如果我将输入子字符串的长度增加几个字符,程序确实会失败。 -- 未定义的行为,简单明了。越界访问数组,任何事情都可能发生,包括“工作”。 我根据该链接更改了问题。 为什么不直接使用std::string呢?我知道你最终会想出“魔法代码”来解决这个问题,因为它所做的只是用缓冲区和指针做一些事情。但是,除了修复错误之外,您能从中获得什么?如果您珍惜时间,请使用std::string。哎呀,你甚至包括&lt;string&gt;,但没有使用任何东西。 您只能在malloc(或null)之前分配的空间上调用realloc ...或realloc,或calloc 【参考方案1】:

首先,如果你想使用 realloc,你不必使用 memmove,因为 realloc 会负责复制数据。

来自男人:

realloc() 函数改变指向的内存块的大小 通过 ptr 到 size 字节。内容将在以下范围内保持不变 区域的开始,直到新旧尺寸中的最小值。

此外,您只能对以前由 malloc、realloc 或 calloc 返回的指针使用 realloc

除非 ptr 为 NULL,否则它一定是由先前对 malloc()、calloc() 或 realloc() 的调用返回的。

所以你需要在你的 main 中使用 malloc

char *stmt = malloc(strlen("replacing this $string ok") + 1);
if (stmt)
    stmt = "replacing this $string ok";

其次,如果要更改调用函数中指针的值,则需要在该指针上使用指针(C 风格)或引用(C++ 风格),否则调用者中的指针将指向旧地址。

原型的 C 风格示例:

void replc(char** in, char* subin);

分配(NewSize 为整数):

*in = realloc(*in, NewSize);

(请记住,如果分配失败,malloc 和 realloc 可能会返回 NULL)

【讨论】:

我似乎有一些关于 -alloc 函数的知识要学习,但这很有帮助。我使用的参数是:(char*&amp; in, ... 并分配有char* p = (char*)calloc(len+sublen, sizeof(char));

以上是关于使用 realloc() 使 memmove() 安全 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

是什么导致realloc()无效的下一个大小错误?

开心模拟—— 用C模拟实现memcpy和memmove函数

memcpy与memmove的区别

C 标准库 - string.h之memmove使用

memcpy 和 memmove

memcpy与memmove