简体   繁体   中英

Why is my code working when I haven't allocated enough memory using malloc()?

I have I am doing this problem on SPOJ. http://www.spoj.com/problems/NHAY/ . It requires taking input dynamically. In the code below even though I am not allocating memory to char *needle using malloc() - I am taking l = 1 - yet I am able to take input of any length and also it is printing out the entire string. Sometimes it gives runtime error. Why is this when I have not allocated enough memory for the string?

#include<stdio.h>
#include<malloc.h>
#include<ctype.h>
#include<stdlib.h>

int main()
{
    long long l;
    int i;
    char *needle;
    while(1){
        scanf("%lld",&l);
        needle =(char *)malloc(sizeof(char)*l);
        scanf("%s",needle);
        i=0;
        while(needle[i]!='\0'){
            printf("%c",needle[i]);
            i++;
        }
        free(needle);
    }
}

I also read on stackoverflow that a string is a char * so I should declare char *needle . How can I use this fact in the code? If I take l = 1 then no matter, what the length of the input string it should contain characters only up to the memory allocated for the char * pointer, ie 1 byte. How can I do that?

Your code is producing an intentional buffer overflow by having sscanf copying a string bigger than the allocated space into the memory allocated by malloc . This "works" because in most cases, the buffer that is allocated is somewhere in the middle of a page so copying more data into the buffer "only" overwrites adjacent data. C (and C++) don't do any array bounds checking on plain C array and thus the error is uncaught.

In the cases where you end up with a runtime error, you most likely copied part of the string into unmapped and unallocated memory, which trigger an access violation.

Memory is usually allocated from the underlying OS in pages of a fixed size. For example, on x86 systems, pages are usually 4k in size. If the mapped address you are writing to is far enough away from the beginning and end of the page, the whole string will fit within the boundaries of the page. If you get close enough to the upper boundary, the code may attempt to write past the boundary, triggering the access violation.

[With some assumptions about the underlying system]

The reason it works for now is that the C library manages pools of memory allocated in pages from the operating system. The operating system only returns pages. The C library returns arbitrary amounts of data.

For your first allocation, you are getting read/write pages allocated by the operating system and managed by the pool. You are going off the edge of the data allocated by the library but are within the page returned by the operating system.

DOing what you are doing will corrupt the structure of the pool and a more extensive program using dynamic memory will eventually crash.

C language do not have default bound check. At the best it will crash while debugging, sometimes it will work as expected. Otherwise you will end up overwriting other memory blocks.

It will not always work. It is Undefined Behaviour .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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