1

I need to remove a specific element from an array, that array is dynamically resized in order to store an unknown number of elements with realloc.

To control the allocated memory and defined elements, I have two other variables:

double *arr = NULL;
int elements = 0;
int allocated = 0;

After some elements being placed in the array, I may need to remove some of them. All texts that I've found says to use memmove and reduce the variables by the number of elements removed.

My doubt is if this method is secure and efficient.

5
  • 1
    Which part of memmove do you think is insecure or inefficient. It's you who chose to write in C, and now you're worried about security of memory operations? Commented Aug 3, 2011 at 17:02
  • 1
    You do realize how awful realloc is to overall memory sytem health (fragmentation, alloc/copy/free time, etc.) Yuck... Commented Aug 3, 2011 at 17:04
  • By secure I mean that I am worried about memory leaks. Because I don't know how exactly memmove works. I don't know what happens the the removed element (it is not a pointer, so it don't need a free call) and if the array was really resized (as I decrease the elements and allocated counters. Commented Aug 3, 2011 at 17:07
  • memmove won't cause leaks, but can trash memory if called with the wrong parameters. This present security vulnerabilities and can lead to a crash / protection fault. Commented Aug 3, 2011 at 17:11
  • do you mean safe by secure ? Commented Feb 24, 2016 at 16:53

4 Answers 4

4

I think this is the most efficient function you can use (memcpy is not an option) regarding secured - you will need to make sure that the parameters are OK, otherwise bad things will happen :)

Sign up to request clarification or add additional context in comments.

Comments

2

Using memmove is certainly efficient, and not significantly less secure than iterating over the array. To know how secure the implementation actually is, we'd need to see the code, specifically the memmove call and how return results from realloc are being checked.

If you get your memmove wrong, or don't check any realloc returns, expect a crash.

Comments

1

In principle, assuming you calculate your addresses and lengths correctly, you can use memmove, but note that if you overwrite one or more elements with the elements at higher indexes, and these overwritten elements were structs that contained pointers to allocated memory, you could produce leaks.

IOW, you must first take care of properly disposing the elements you are overwriting before you can use memmove. How you dispose them depends on what they represent. If they are merely structs that contain pointers into other structures, but they don't "own" the allocated memory, nothing happens. If the pointers "own" the memory, it must be deallocated first.

1 Comment

It is an array of structs that contains just simple double data, not pointers.
0

The performance of memmove() and realloc() can be increased by data partitioning. By data partitioning I mean to use multiple array chunk rather than one big array.

Apart from memmove(), I found memory swaping is efficient way. But there is drawback. The array order may be changed in this way.

int remove_element(int*from, int total, int index) {
        if(index != (total-1))
                from[index] = from[total-1];
        return total-1; // return the number of elements
}

Interestingly array is randomly accessible by the index. And removing randomly an element may impact the indexes of other elements as well. If this remove is done in a loop traversal on the array, then the reordering may case unexpected results.

One way to fix that is to use a is_blank mask array and defer removal.

int remove_element(int*from, int total, int*is_valid, int index) {
        is_blank[index] = 1;
        return total; // **DO NOT DECREASE** the total here
}

It may create a sparse array. But it is also possible to fill it up as new elements are added in the blank positions.

Again, it is possible to make the array compact in the following efficient swap algorithm.

int sparse_to_compact(int*arr, int total, int*is_valid) {
        int i = 0;
        int last = total - 1;
        // trim the last blank elements
        for(; last >= 0 && is_blank[last]; last--); // trim blank elements from last

        // now we keep swapping the blank with last valid element
        for(i=0; i < last; i++) {
                if(!is_blank[i])
                        continue;
                arr[i] = arr[last]; // swap blank with the last valid
                last--;
                for(; last >= 0 && is_blank[last]; last--); // trim blank elements
        }
        return last+1; // return the compact length of the array
}

Note that the algorithm above uses swap and it changes the element order. May be it is preferred/safe to be used outside of some loop operation on the array. And if the indices of the elements are saved somewhere, they need to be updated/rebuilt as well.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.