문제

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

int main()
{
    char* s = (char*)malloc(sizeof(char) * 3); //I allocate memory for 3 chars
    s[0] = 'a';
    s[1] = 'b';
    s[2] = '\0';
    s[3] = 'd'; //This shouldn't work

    std::cout << s[3] << std::endl; //It prints out d, why?

    free(s);        
    return 0;
}

Why am I allowed to write to s[3]?

도움이 되었습니까?

해결책 2

Usually function malloc allocates some minimum number of bytes for example 16 even if you will request to allocate only one (or 3 as in your example) byte(s).

However you shall not rely on such feature of the function. It is implementation defined how malloc allocates memory. So your code has undefined behaviour.

다른 팁

This is called undefined behavior.

The compiler does not prevent you from doing illegal things; however, the compiled code may not do what you expect.

The process may even allow to write on s[100], but it will corrupt the process address space in most cases and creating difficult to debug problems. Sometimes write to such location will cause segmentation fault if the address being written doesn't fall in process address space, but we won't get the access violation always as the address may very fall in the address space of the process.

Basically, in C/C++ these are some of the issues people should be very careful about. Because the corruption of memory gets manifested in some other places causing weird behavior and we need to spend hours looking for the needle in the haystack. Tools like electric-fence, Valgrind, cppcheck help in isolating such errors, but even they may fail to detect the cause of memory corruption. Especially electric-fence will work only for small programs, cppcheck can only do static checks and valgrind will slow down the process considerably.

You are writing in memory that you do not own. You can do that, but it is violating your address space, potentially causing segmentation faults.

In this case, it's working and printing d, but it is not guaranteed to happen in other machines or even in code compiled by other compilers in your own machine. It's called undefined behavior.

Why am I allowed to write to s[3]?

Because you're not forbidden to do that.

This will cause undefined behavior since you're trying to touch memory that is not allocated for you.

s[3] = 'd'; It could invoke undefined behavior. It will not stop you from writing to adjacent memory location but will behave differently when you access it since it is not allocated by you.

You are writing to an unallocated memory location. If this location belongs to another program then your program may behave erroneously. If it belongs to the OS reserved memory then you may get segmentation fault or program crash. This is undefined behavior.

Ah, this sort of question pops up every week…

One thing that must be stated in every C tutorial: the environment of the C library and the runtime do not guarantee that any misuse, mistyped access or other not-well-defined operation will be caught and properly reported as such. Main point of this is efficiency. You obey the rules (and are responsible for them to be fulfilled), and the runtime is built around them, efficiently proxying the programming environment model down to hardware and to the kernel.

Note about why this is happening. The environment you see in C and it's runtime library is much simpler than underlying mechanisms that actually do the job. In this case, you see that malloc got a big chunk of memory from the system onto process's dynamic data section and returned address of smaller sub-chunk, and remembered that it is in use in it's own structures. What your code is trying to perform is called buffer overflow. And what it really does is: trashing internal structures of malloc, or writing to another allocated chunk (resulting in serious delayed problems), or writing to unallocated section (resulting in absolutely no problems in current process's future).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top