Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
250 views
in Technique[技术] by (71.8m points)

c - What happens if I try to access memory beyond a malloc()'d region?

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...