简体   繁体   English

如果我在用calloc分配的内存之外设置值,会发生什么?

[英]What happens if I set a value outside of the memory allocated with calloc?

Consider the following: 考虑以下:

int* x = calloc(3,sizeof(int));
x[3] = 100;

which is located inside of a function. 位于函数内部。

I get no error when I compile and run the program, but when I run it with valgrind I get an "Invalid write of size 4". 编译并运行程序时没有错误,但是使用valgrind运行该程序时,出现“大小为4的无效写入”。

I understand that I am accessing a memory place outside of what I have allocated with calloc, but I'm trying to understand what actually happens. 我了解我正在访问用calloc分配的内存之外的存储空间,但是我试图了解实际发生的情况。

Does some address in the stack(?) still have the value 100? 堆栈中的某些地址(?)是否仍为100? Because there must certainly be more available memory than what I have allocated with calloc. 因为肯定有比我用calloc分配的更多的可用内存。 Is the valgrind error more of a "Hey, you probably did not mean to do that"? valgrind错误更像是“嘿,您可能不是故意这样做的”吗?

I understand that I am accessing a memory place outside of what I have allocated with calloc, but I'm trying to understand what actually happens. 我了解我正在访问用calloc分配的内存之外的存储空间,但是我试图了解实际发生的情况。

"What actually happens" is not well-defined; “实际发生的事情”没有明确定义; it depends entirely on what gets overwritten. 这完全取决于被覆盖的内容。 As long as you don't overwrite anything important, your code will appear to run as expected. 只要你不覆盖任何东西重要的是,你的代码将出现按预期运行。

You could wind up corrupting other data that was allocated dynamically. 您可能破坏了动态分配的其他数据。 You could wind up corrupting some bit of heap bookkeeping. 您可能会破坏一些堆簿记。

The language does not enforce any kind of bounds-checking on array accesses, so if you read or write past the end of the array, there are no guarantees on what will happen. 该语言不会对数组访问进行任何形式的边界检查,因此,如果您在数组末尾进行读取或写入操作,则无法保证会发生什么。

There's no guarantees on what was allocated in the space past x[3] or what will be written there in the future. 无法保证在x[3]之后的空间中分配了什么,或者将来会写入什么。 alinsoar mentioned that x[3] itself does not cause undefined behavior, but you should not attempt to fetch or store a value from there. alinsoar提到x[3]本身不会引起未定义的行为,但您不应尝试从那里获取或存储值。 Often you will probably be able to write and access this memory location without problems, but writing code that relies on reaching outside of your allocated arrays is setting yourself up for very hard to find errors in the future. 通常,您可能可以毫无问题地编写和访问该内存位置,但是编写依赖于到达分配的数组之外的代码会使自己为将来很难发现错误做好准备。

Does some address in the stack(?) still have the value 100? 堆栈中的某些地址(?)是否仍为100?

When using calloc or malloc, the values of the array are not actually on the stack. 使用calloc或malloc时,数组的值实际上不在堆栈上。 These calls are used for dynamic memory allocation, meaning they are allocated in a seperate area of memory known as the "Heap". 这些调用用于动态内存分配,这意味着它们被分配在称为“堆”的单独的内存区域中。 This allows you to access these arrays from different parts of the stack as long as you have a pointer to them. 这使您可以从堆栈的不同部分访问这些数组,只要您有指向它们的指针即可。 If the array were on the stack, writing past the bounds would risk overwriting other information contained in your function (like in the worst case the return location). 如果数组在堆栈上,则越界写入可能会覆盖函数中包含的其他信息(例如在最坏的情况下返回位置)。

Does some address in the stack(?) still have the value 100? 堆栈中的某些地址(?)是否仍为100?

First of all, calloc allocates memory on the heap not stack. 首先, calloc在堆而不是堆栈上分配内存。

Now, regarding the error. 现在,关于错误。

Sure most of the time there is plenty of memory available when your program is running. 确保在大多数情况下,程序运行时有足够的可用内存。 However when you allocate memory for x bytes, the memory manager looks for some free chunk of memory of that exact size(+ maybe some more if calloc requested larger memory to store some auxiliary info), there are no guaranties on what the bytes after that chunk are used for, and even no guaranties that they are not read-only or can be accessed by your program. 但是,当您为x个字节分配内存时,内存管理器会寻找一些确切大小的空闲内存块(如果calloc请求更大的内存来存储一些辅助信息,则可能会更多),对于之后的字节数没有任何保证。块用于,甚至不保证它们不是只读的,也不能由您的程序访问。

So anything can happen. 所以什么都可能发生。 In the case if the memory was just there waiting for it to be used by your program, nothing horrible happens, but if that memory was used by something else in your program, the values would be mess up, or worst of all the program could crash because of accessing something that wasn't supposed to be accessed. 在这种情况下,如果只是内存在等待程序使用,就不会发生可怕的事情,但是,如果该内存被程序中的其他人使用,则值将被弄乱,否则所有程序都可能变坏由于访问了不应访问的内容而崩溃。

So the valgrind error should be treated very seriously. 因此应非常认真地对待valgrind错误。

The C language doesn't require bounds checking on array accesses, and most C compilers don't implement it. C语言不需要对数组访问进行边界检查,并且大多数C编译器都没有实现它。 Besides if you used some variable size instead of constant value 3, the array size could be unknown during compilation, and there would be no way to check if the access isn't out of bound. 此外,如果您使用一些可变大小而不是常量3,那么在编译过程中数组大小可能是未知的,并且无法检查访问是否不受限制。

The act of doing that is what is called undefined behavior . 这样做的行为就是所谓的未定义行为 Literally anything can happen, or nothing at all. 从字面上看,任何事情都会发生,或者什么都不会发生。

Even though you are Stupid, I give you extra points for testing with Valgrind. 即使您很笨,我也为您提供了使用Valgrind进行测试的额外要点。

In practice, it is likely you will find the value 100 in the memory space after your array. 实际上,您可能会在数组之后的内存空间中找到值100。

Beware of nasal demons . 当心鼻恶魔

You're allocating memory for 3 integer elements but accessing the 4th element ( x[3] ). 您正在为3个整数元素分配内存,但是要访问第4个元素( x[3] )。 Hence, the warning message from valgrind. 因此,来自valgrind的警告消息。 Compiler will not complain about it. 编译器不会对此抱怨。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM