Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using unallocated memory without error?

Why does that work?

#include <iostream>
using namespace std;

int main() {
    float* tab[3];

    int i = 0;
    while(i < 3) {
        tab[i] = new float[3-i];
        i++;
    }

    cout << tab[2][7] << endl;
    tab[2][7] = 6.87;
    cout << tab[2][7] << endl;

    i = 0;
    while(i < 3)
        delete[] tab[i];
}

while this one doesn't?

#include <iostream>
using namespace std;

int main() {
    float* tab = new float[3];

    cout << tab[7] << endl;
    tab[7] = 6.87;
    cout << tab[7] << endl;

    delete[] tab;
}

I tried both programs on Win XP with MS VS 2008, both compiled without errors and the first one ran without any errors. The second made pop up some error window, however I can't remember it and can't reproduce (no access to Windows at the moment).

I tried them also on Linux (Kubuntu 10.10 with precompiled kernel package version 2.6.35.23.25) with g++ and both compile and run without any errors.

Why? Shouldn't there be any pop-ups with something like "Wrong access to unallocated memory"?

I know it should (and, luckily, does) compile without errors, but I thought it shouldn't run without them... And why the second example makes errors on Windows and not on Linux?

like image 530
silmeth Avatar asked Nov 30 '10 17:11

silmeth


People also ask

What happens if you free unallocated memory?

Before freeing a pointer, the programmer should make sure that the pointer was previously allocated on the heap and that the memory belongs to the programmer. Freeing an unallocated pointer will cause undefined behavior in the program.

How to avoid double free in c++?

Double Free A simple technique to avoid this type of vulnerability is to always assign NULL to a pointer after it has been freed. Subsequent attempts to free a null pointer will be ignored by most heap managers.

What happens if free () fails?

The free function returns no value.

How to solve memory error in C?

delete s; To avoid mismatched allocation/deallocation, ensure that the right deallocator is called. In C++, new[] is used for memory allocation and delete[] for freeing up. In C, malloc(), calloc() and realloc() functions are used for allocating memory while the free() function is used for freeing up allocated memory.


4 Answers

Use of unallocated memory results in undefined behaviour. You can have no expectations of what will happen when you do this even on the same system and compiler, let alone across different combinations of hardware and compiler.

The program might crash immediately, it might work for a while and then fail later, it might even appear to work perfectly.

Accessing memory you don't own is always a programming error, though. Don't think of the appearance of correct operation as "it sometimes works", think of it as "I got really unlucky and my bug does not show up quickly".

like image 137
Steve Townsend Avatar answered Oct 14 '22 07:10

Steve Townsend


While the other answers, with the exception of Mark's, are not wrong they are not exactly right either. What you are doing by accessing data past the end of what you've explicitly allocated in your program is causing "undefined behavior". It can do anything, including "work".

Steve's answer didn't exist when I began writing this.

like image 43
Edward Strange Avatar answered Oct 14 '22 05:10

Edward Strange


Both of them do out-of-bounds array access - you have an array of 3 float pointers, and you're accessing the 8th array. This is bound to crash.

However, unlike Java or some other managed languages, there is no explicit bounds checking for each array access (since the performance cost of that is prohibitive). So the only bounds checking you have is your MMU. If you end up accessing memory that does not belong to your application, you'll crash. If you hit memory that is not allocated but still happens to be part of your process (could be a guard word, for example), it'll silently succeed. This is a great recipe for very-hard-to-track-down bugs.

Bounds checking is key. Do it whenever you can.

like image 5
EboMike Avatar answered Oct 14 '22 06:10

EboMike


In the first example, tab[2] has a value that points to valid memory. tab[2]+7 isn't allocated, But It Could Be. No seg-fault.

In the second, tab[7] has no value... it's random bits (possibly zeros, or 0xDEADBEEF or just whatever value was there last). This almost certainly does not point to memory that is valid for this application to access. Thus: boom.

like image 1
Mark Storer Avatar answered Oct 14 '22 07:10

Mark Storer