我用 char* memoryChunk = malloc ( 80* sizeof(char) + 1);
分配了一 block 内存是什么阻止我写入超过 81 个单元的内存位置?我能做些什么来防止这种情况发生?
void testStage2(void) {
char c_str1[20] = "hello";
char* ut_str1;
char* ut_str2;
printf("Starting stage 2 tests\n");
strcat(c_str1, " world");
printf("%s\n", c_str1); // nothing exciting, prints "hello world"
ut_str1 = utstrdup("hello ");
ut_str1 = utstrrealloc(ut_str1, 20);
utstrcat(ut_str1, c_str1);
printf("%s\n", ut_str1); // slightly more exciting, prints "hello hello world"
utstrcat(ut_str1, " world");
printf("%s\n", ut_str1); // exciting, should print "hello hello world wo", 'cause there's not enough room for the second world
}
char* utstrcat(char* s, char* suffix){
int i = strlen(s),j;
int capacity = *(s - sizeof(unsigned) - sizeof(int));
for ( j =0; suffix[j] != '\0'; j++){
if ((i+j-1) == 20)
return s;
s[i+j] = suffix[j];
}
//strcpy(s, suffix);
s[i + j] = '\0';
return s;
}// append the suffix to s
最佳答案
What is keeping me from writing into the memory location beyond 81 units?
没有。但是,这样做会导致未定义的行为。这意味着任何事情 都可能发生,您不应该依赖它重复做同样的事情。 99.999% 的情况下这是错误。
What can I do to prevent that?
在访问(读取或写入)它们之前,请始终检查您的指针是否在范围内。传递给字符串函数时,始终确保字符串以 \0
结尾。
您可以使用valgrind等调试工具来协助您定位与越界指针和数组访问相关的错误。
stdlib 的方法
对于您的代码,您可以使用 utstrncat
,它的作用类似于 utstrcat
,但具有最大大小(即缓冲区的大小)。
stdc++的方法
您还可以在 C++ 中创建数组结构/类或使用 std::string
。例如:
typedef struct UtString {
size_t buffer_size;
char *buffer;
} UtString;
然后让您的函数对其进行操作。您甚至可以使用此技术进行动态重新分配(但这似乎不是您想要的)。
缓冲区结束标记方法
另一种方法是使用缓冲区结束 标记,类似于字符串结束 标记。当您遇到标记时,不要写入该位置或它之前的位置(对于字符串标记的结尾)(或者您可以重新分配缓冲区以便有更多空间)。
例如,如果您将 "hello world\0xxxxxx\1"
作为字符串(其中 \0
是字符串标记的结尾,\1
是缓冲区结束标记,x
是随机数据)。附加 "this is fun"
将如下所示:
hello world\0xxxxxx\1
hello world \0xxxxx\1
hello world t\0xxxx\1
hello world th\0xxx\1
hello world thi\0xx\1
hello world this\0x\1
hello world this \0\1
*STOP WRITING* (next bytes are end of string then end of buffer)
你的问题
你的代码的问题在这里:
if ((i+j-1) == 20)
return s;
虽然您在溢出缓冲区之前停止,但您并未标记字符串的结尾。
您可以使用 break
提前结束 for
循环,而不是返回。这将导致 for
循环之后的代码运行。这将设置字符串标记的结尾并返回您想要的字符串。
此外,我担心您的分配中可能存在错误。您有 + 1
来分配字符串之前的大小,对吗?有个问题:unsigned
通常不是1个字符;为此,您将需要 + sizeof(unsigned)
。我还会编写 utget_buffer_size
和 utset_buffer_size
以便您可以更轻松地进行更改。
关于c - 如果我尝试访问超出 malloc() 区域的内存,会发生什么情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1655971/