tags:

views:

134

answers:

8

Hi All,

I have two character array of size 100 (char array1[100], char array2[100]). Now i just want to check whether anybody is accessing array beyond the limit or not. Its necessary because suppose allocated memory for array1 and array2 are consecutive means as the array1 finish then array2 starts. Now if anyone write: array1[101], conceptually its wrong but compiler will give warning but will not crash. So How can i detect this problems and solve it?

Update 1:

I already have a code of line 15,000. And for that code i have to check this condition and i can invoke my functions but cannot change the written code. Please suggest me according to this.

+2  A: 

My initial response to this would be to wrap the access to these arrays in a function or method and send the index as a parameter. If the index is out of bounds, raise an exception or report the error in some other way.

EDIT: This is of course a run-time prevention. Don't know how you would check this at compile time if the compiler cannot checkt this for you. Also, as Kolky has already pointed out, it'd be easier to answer this if we know which language you are using.

gablin
i am using c++ language.
max_dev
A: 

I'm assuming you're writing in C++ or C. As long as you can continuously check the value of the first array element in the second array, you'll be fine. Better yet, if you would instead malloc or new depending on which language 1 byte more before and after each array, filling them with 0xDEADBEEF you'd find that if something was changed, these would show it.

EDIT:

Since you're in C++, I'm going to go ahead and suggest using vectors in your code. You'll get runtime checking with .at(), which throws an exception if you try to access a point outside of the bounds of the vector. In addition, if you need to interface with a C library, then you can pass in the address of the first item within the vector. Vectors are guaranteed to have their memory be contiguous.

wheaties
Will the fragmentation not occur in that case?
max_dev
It does nothing to prevent the fragmentation, however, it does allow you to check if the value of `0xDEADBEEF` has changed or not. However, now that I know you're using C++ I'm going to recommend that you use vectors instead of arrays.
wheaties
+2  A: 

Most modern languages will detect this and prevent it from happening. C and its derivatives don't detect this, and basically can't detect this, because of the numerous ways you can access the memory, including bare pointers. If you can restrict the way you access the memory, then you can possibly use a function or something to check your access.

Paul Tomblin
A: 

In C/C++, there is no general solution. You can't do it at compile time since there are too many ways to change memory in C. Example:

char * ptr = &array2;
ptr = foo(ptr); // ptr --;

ptr now contains a valid address but the address is outside of array2. This can be a bug or what you want. C can't know (there is no way to say "I want it so" in C), so the compiler can't check it. Sililarily:

char * array2 = malloc(100);

How should the C compiler know that you are treating the memory as a char array and would like a warning when you write &array2[100]?

Therefore, most solutions use "mungwalls", i.e. when you call malloc(), they will actually allocate 16/32 bytes more than you ask for:

malloc(size) {
    mungwall_size = 16;
     ptr = real_malloc(size + mungwall_size*2);
     createMungwall(ptr, mungwall_size);
     createMungwall(ptr+size, mungwall_size);
     return ptr+size;
}

in free() it will check that 16 bytes before and after the allocated memory area haven't been touched (i.e. that the mungwall pattern is still intact). While not perfect, it makes your program crash earlier (and hopefully closer to the bug).

You could also use special CPU commands to check all memory accesses but this approach would make your program 100 to 1 million times slower than it is now.

Therefore, languages after C don't allow pointers which means "array" is a basic type which has a size. Now, you can check every array access with a simple compare.

If you want to write code in C which is save, you must emulate this. Create an array type, never use pointers or char * for strings. It means you must convert your data type all the time (because all library functions use const char * for strings) but it makes your code safer.

Languages do age. C is now 40 years old and our knowledge has moved on. It's still used in a lot of places but it shouldn't be the first choice anymore. The same applies (to a lesser extend) to C++ because it suffers from the same fundamental flaws of C (even though you now have libraries and frameworks which work around many of them).

Aaron Digulla
Downvoted. In C++ it's easy to write a wrap. Stating that there is no general solution in C++ is flat out wrong.
DeadMG
I said "there are frameworks which work around many of them". But a lot of dumb C code does compile with C++ and by calling the wrong function with the wrong arguments, you can get a feeling of building a card house.
Aaron Digulla
+1  A: 

If you are using C++ rather than C there any reason you can't use std::vector? That will give you bounds checking if the user goes outside your range. Am I missing something here?

Wouldn't it be sensible to prevent the user having direct access to the collections in the first place?

Robin Welch
A: 

If you're in C++ you can write a quick wrapper class.

template<typename T, int size> class my_array_wrapper {
    T contents[size];
public:
    T& operator[](int index) {
        if (index >= size)
            throw std::runtime_error("Attempted to access outside array bounds!");
        if (index < 0)
            throw std::runtime_error("Attempted to access outside array bounds!");
        return contents[index];
    }
    const T& operator[](int index) const {
        if (index >= size)
            throw std::runtime_error("Attempted to access outside array bounds!");
        if (index < 0)
            throw std::runtime_error("Attempted to access outside array bounds!");
        return contents[index];
    }
    operator T*() {
        return contents;
    }
    operator const T*() const {
        return contents;
    }
};

my_array_wrapper<char, 100> array1;
array1[101]; // exception

Problem solved, although if you access through the pointer decay there will be no bounds checking. You could use the boost::array pre-provided solution.

DeadMG
Why reinvent the wheel? there are existing solutions to this problem that have been proven and save the OP testing his/her own version.
Steve Townsend
I just edited with that.
DeadMG
I'd throw `out_of_range`, rather than `runtime_error`, like `vector::at()` does. Also, I'd make `index` and `size` of type `size_t` so I don't have to compare with 0.
Mike Seymour
Meh. It's not supposed to be idealistic perfect working code, but a starting point.
DeadMG
A: 

If you ran a static analyser (i.e. cppcheck) against your code it would give you a bounds error http://en.wikipedia.org/wiki/User:Exuwon/Cppcheck#Bounds_checking

to solve it... you'd be better off using a container of some sorts (i.e. std::vector) or writing a wrapper

queBurro
A: 

If you use boost::array or similar you will get an exception range_error if array bounds are overstepped. http://www.boost.org/doc/libs/1_44_0/doc/html/boost/array.html. Boost is fabulous.

Steve Townsend