如果我尝试访问 malloc() 区域之外的内存会发生什么? [英] What happens if I try to access memory beyond a malloc()'d region?

查看:26
本文介绍了如果我尝试访问 malloc() 区域之外的内存会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经用 char* memoryChunk = malloc ( 80* sizeof(char) + 1); 分配了一块内存;是什么阻止我写入超过 81 个单位的内存位置?我能做些什么来防止这种情况发生?

I've allocated a chuck of memory with char* memoryChunk = malloc ( 80* sizeof(char) + 1); What is keeping me from writing into the memory location beyond 81 units? What can I do to prevent that?

void testStage2(void) {
 char c_str1[20] = "hello";
 char* ut_str1;
 char* ut_str2;

 printf("Starting stage 2 tests
");
 strcat(c_str1, " world");
 printf("%s
", c_str1); // nothing exciting, prints "hello world"

 ut_str1 = utstrdup("hello ");
 ut_str1 = utstrrealloc(ut_str1, 20);
 utstrcat(ut_str1, c_str1);
 printf("%s
", ut_str1); // slightly more exciting, prints "hello hello world"

 utstrcat(ut_str1, " world");
 printf("%s
", 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] != ''; j++){
  if ((i+j-1) == 20)
   return s;
  s[i+j] = suffix[j];
 }
 //strcpy(s, suffix);
 s[i + j] = '';
 return s;
}// append the suffix to s

推荐答案

是什么让我无法写入超过 81 个单位的内存位置?

What is keeping me from writing into the memory location beyond 81 units?

没什么.但是,这样做会导致未定义的行为.这意味着任何事情都可能发生,你不应该依赖它两次做同样的事情.99.999% 的情况下这是一个错误.

Nothing. However, doing this results in undefined behaviour. This means anything can happen, and you shouldn't depend on it doing the same thing twice. 99.999% of the time this is a bug.

我能做些什么来防止这种情况发生?

What can I do to prevent that?

在访问(读取或写入)它们之前,始终检查您的指针是否在边界内.传递给字符串函数时,始终确保字符串以 结尾.

Always check that your pointers are within bounds before accessing (reading from or writing to) them. Always make sure strings end with when passing to string functions.

您可以使用 valgrind 等调试工具来帮助您定位与越界指针和数组访问相关的错误.

You can use debugging tools such as valgrind to assist you in locating bugs related to out-of-bounds pointer and array access.

对于您的代码,您可以使用 utstrncat,它的作用类似于 utstrcat,但采用最大大小(即缓冲区的大小).

For your code, you can have utstrncat which acts like utstrcat but takes a maximum size (i.e. the size of the buffer).

您还可以在 C++ 中创建数组结构/类或使用 std::string.例如:

You can also create an array struct/class or use std::string in C++. For example:

typedef struct UtString {
    size_t buffer_size;
    char *buffer;
} UtString;

然后让您的函数对其进行操作.您甚至可以使用这种技术进行动态重新分配(但这似乎不是您想要的).

Then have your functions operate on that instead. You can even have dynamic reallocation using this technique (but that doesn't seem to be what you want).

另一种方法是使用缓冲区结束标记,类似于字符串结束标记.当您遇到标记时,不要写入该位置或之前的位置(用于字符串标记的结尾)(或者您可以重新分配缓冲区以便有更多空间).

Another approach is to have an end of buffer marker, similar to the end of string marker. When you encounter the marker, don't write to that place or one before it (for the end of string marker) (or you can reallocate the buffer so there's more room).

例如,如果您将 "hello worldxxxxxx1" 作为字符串(其中 是字符串标记的结尾,1 是缓冲区结束标记,x 是随机数据).附加 "this is fun" 看起来像下面这样:

For example, if you have "hello worldxxxxxx1" as a string (where is the end of string marker, 1 is the end of buffer marker, and the x are random data). appending " this is fun" would look like the following:

hello worldxxxxxx1
hello world xxxxx1
hello world txxxx1
hello world thxxx1
hello world thixx1
hello world thisx1
hello world this 1
*STOP WRITING* (next bytes are end of string then end of buffer)

你的问题

您的代码有问题:

Your problem

The problem with your code is here:

  if ((i+j-1) == 20)
   return s;

尽管您在溢出缓冲区之前停止,但您并未标记字符串的结尾.

Although you are stopping before overrunning the buffer, you are not marking the end of the string.

您可以使用 break 提前结束 for 循环,而不是返回.这将导致 for 循环之后的代码运行.这将设置字符串标记的结尾并返回字符串,这正是您想要的.

Instead of returning, you can use break to end the for loop prematurely. This will cause the code after the for loop to run. This sets the end of string marker and returns the string, which is what you want.

此外,我担心您的分配中可能存在错误.你有 +1 来分配字符串前的大小,对吗?有一个问题:unsigned 通常不是 1 个字符;为此,您将需要 + sizeof(unsigned).我还会编写 utget_buffer_sizeutset_buffer_size 以便您可以更轻松地进行更改.

In addition, I fear there may be a bug in your allocation. You have + 1 to allocate the size before the string, correct? There's a problem: unsigned is usually not 1 character; you will need + sizeof(unsigned) for that. I would also write utget_buffer_size and utset_buffer_size so you can make changes more easily.

这篇关于如果我尝试访问 malloc() 区域之外的内存会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆