Pergunta

I have encountered a problem which I don't understand, the following is my code:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cstdlib>
using namespace std;

int main(int argc, char **argv)
{
    char *format = "The sum of the two numbers is: %d";
    char *presult;
    int sum = 10;
    presult = (char *)calloc(sizeof(format) + 20, 1);   //allocate 24 bytes

    sprintf(presult, format, sum);  // after this operation, 
                                    // the length of presult is 33
    cout << presult << endl;

    presult[40] = 'g';   //still no segfault here...
    delete(presult);
}

I compiled this code on different machines. On one machine the sizeof(format) is 4 bytes and on another, the sizeof(format) is 8 bytes; (On both machines, the char only takes one byte, which means sizeof(*format) equals 1)

However, no matter on which machine, the result is still confusing to me. Because even for the second machine, the allocated memory for use is just 20 + 8 which is 28 bytes and obviously the string has a length of 33 meaning that at least 33 bytes are needed. But there is NO segmentation fault occurring after I run this program. As you can see, even if I tried to dereference the presult at position 40, the program doesn't crash and show any segfault information.

Could anyone help to explain why? Thank you so much.

Foi útil?

Solução

Accessing unallocated memory is undefined behavior, meaning you might get a segfault (if you're lucky) or you might not.

Or your program is free to display kittens on the screen.

Speculating on why something happens or doesn't happen in undefined behavior land is usually counter-productive, but I'd imagine what's happening to you is that the OS is actually assigning your application a larger block of memory than it's asking for. Since your application isn't trying to dereference anything outside that larger block, the OS doesn't detect the problem, and therefore doesn't kill your program with a segmentation fault.

Outras dicas

Because undefined behavior is undefined. It's not "defined to crash".

There is no seg fault because there is no reason for there to be one. You are very likely stil writing into the heap since you got memory from the heap, so the memory isn't read only. Also, the memory there is likely to exist and be allocated for you(or at least the program), so it's not an access violation. Normally you would get a seg fault because you might try to access memory that is not given to you or you may be trying to write to memory that is read only. Neither of these appears to be the case here, so nothing goes wrong.

In fact, writing past the end of a buffer is a common security problem, known as the buffer overflow. It was the most common security vulnerability for some time. Nowadays people are using higher level languages which check for out of index bounds, so this is not as big of a problem anymore.

To respond to this: "the result is still confusing to me. Because even for the second machine, the allocated memory for use is just 20 + 8 which is 28 bytes and obviously the string has a length of 33 meaning that at least 33 bytes are needed."

sizeof(some_pointer) == sizeof(size_t) on any infrastructure. You were testing on a 32bit machine (4B) and on a 64bit machine (8B).

You have to give malloc the number of bytes to allocate; sizeof(ptr_to_char) will not give you the length of the string (the number of chars until '\0').

Btw, strlen does what you want: http://www.cplusplus.com/reference/cstring/strlen/

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top