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

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

问题描述

我已经分配的内存卡盘的char * memoryChunk =的malloc(80 * sizeof的(字符)+ 1); 什么是让我从写入存储器位置超过81台?我可以做prevent什么?

 无效testStage2(无效){
 焦炭c_str1 [20] =你好;
 字符* ut_str1;
 字符* ut_str2; 的printf(启动第2阶段测试\\ n);
 strcat的(c_str1,世界);
 的printf(%S \\ n,c_str1); //平平淡淡,输出Hello World ut_str1 = utstrdup(你好);
 ut_str1 = utstrrealloc(ut_str1,20);
 utstrcat(ut_str1,c_str1);
 的printf(%S \\ n,ut_str1); //稍微更精彩,打印Hello Hello World的 utstrcat(ut_str1,世界);
 的printf(%S \\ n,ut_str1); //令人兴奋的,应打印你好你好世界禾,因为没有足够的空间用于第二世界
}字符* utstrcat(字符* S,字符*后缀){
 INT I = strlen的(S),J;
 INT容量= *(S - 的sizeof(无符号) - 的sizeof(INT));
 为(J = 0;!后缀[J] ='\\ 0'; J ++){
  如果((I + J-1)== 20)
   返回S;
  S [I + J] =后缀[J]。
 }
 //的strcpy(S,后缀);
 S [I + J] ='\\ 0';
 返回S;
} //追加后缀为s


解决方案

  

是什么让我从写入到存储器位置超出81单位的?


没有。但是,这样做导致的未定义行为即可。这意味着的任何的可能发生,你不应该依赖于它做同样的事情两次。这个时间99.999%,是一个错误。


  

我能做些什么,以prevent呢?


经常检查你的指针范围内访问(读取或写入)之前。始终确保字符串与结束\\ 0 传递给字符串函数的时候。

您可以使用调试工具,如以Valgrind的帮助您查找相关的出界外指针和数组访问错误。

STDLIB的做法

有关您的code,你可以有 utstrncat 这就像 utstrcat ,但需要的最大尺寸(即缓冲区的大小)

STDC ++的做法

您也可以创建一个数组结构/类或使用的std ::字符串在C ++中。例如:

  typedef结构UtString {
    为size_t BUFFER_SIZE;
    字符*缓冲区;
} UtString;

然后让你的功能上,而不是工作。你甚至可以使用这种技术动态重新分配(但似乎并没有被你想要的)。

结束缓冲标记方法

另一种方法是为具有的缓冲器的结束的标记,类似的串的结束的标记。当你遇到标记,不写那个地方或者一个前(字符串标记的结尾)(或者你可以重新分配缓冲区,以便有更多的房间)。

例如,如果您有的hello world \\ 0xxxxxx \\ 1作为一个字符串(其中 \\ 0 是字符串标记的结尾, \\ 1 是缓冲标记的结束,而 X 是随机的数据)。追加这很有趣将如下所示:

 的hello world \\ 0xxxxxx \\ 1
世界你好\\ 0×××××\\ 1
世界你好ŧ\\ 0XXXX \\ 1
世界你好日\\ 0XXX \\ 1
世界你好THI \\ 0XX \\ 1
世界你好这个\\ 0X \\ 1
世界你好这个\\ 0 \\ 1
*停止写作*(下一个字节是字符串的结尾然后结束缓冲区)

您的问题

与code中的问题是在这里:

  IF((I + J-1)== 20)
   返回S;

虽然你超越缓冲区之前停止,你是不是标志着字符串的结尾。

而不是返回,可以使用结束循环prematurely的。这将导致在的code为循环运行。此设置字符串标记的结尾,并返回字符串,这是你想要的。

另外,我担心有可能是在您的分配中的错误。您有 + 1 的字符串之前分配的大小,是否正确?还有一个问题:无符号通常不是1个字符;你将需要 +的sizeof(无符号)为。我也写 utget_buffer_size utset_buffer_size 让您可以更轻松地做出改变。

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\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?

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 \0 when passing to string functions.

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

stdlib's approach

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

stdc++'s approach

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).

End-of-buffer marker approach

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).

For example, if you have "hello world\0xxxxxx\1" as a string (where \0 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 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)

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.

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.

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()'D区会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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