使用 realloc() 使 memmove() 安全
Making memmove() safe using realloc()
在我的函数中替换一个子字符串。如果输入的子字符串比原来的长,它会将输入字符串的一部分移出以为输入子字符串腾出空间。
我了解这会导致未定义的行为。我认为我应该能够通过使用 realloc() 分配所需的 space 但没有成功。
我尝试在 memmove() 之前添加这个:
char *newspc = (char*)realloc(in,len+sublen);
in = newspc;
这是一个合理的策略吗?这个操作做space的正确方法是什么?
这是不使用 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)] = '[=11=]';
}
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)] = '[=11=]';
}
}
首先,如果您想使用 realloc,则不必使用 memmove,因为 realloc 会负责复制数据。
来自男人:
The realloc() function changes the size of the memory block pointed to
by ptr to size bytes. The contents will be unchanged in the range from
the start of the region up to the minimum of the old and new sizes.
此外,您只能对之前由 malloc、realloc 或 callocreturn编辑的指针使用 realloc
Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or 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 可以 return NULL)
在我的函数中替换一个子字符串。如果输入的子字符串比原来的长,它会将输入字符串的一部分移出以为输入子字符串腾出空间。
我了解这会导致未定义的行为。我认为我应该能够通过使用 realloc() 分配所需的 space 但没有成功。
我尝试在 memmove() 之前添加这个:
char *newspc = (char*)realloc(in,len+sublen);
in = newspc;
这是一个合理的策略吗?这个操作做space的正确方法是什么?
这是不使用 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)] = '[=11=]';
}
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)] = '[=11=]';
}
}
首先,如果您想使用 realloc,则不必使用 memmove,因为 realloc 会负责复制数据。
来自男人:
The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes.
此外,您只能对之前由 malloc、realloc 或 callocreturn编辑的指针使用 realloc
Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc().
所以你需要在 main
中使用 mallocchar *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 可以 return NULL)