Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

memcpy segfault with larger arrays

I have a function that swaps 2d arrays in C by using memcpy. I know you can swap pointers but I'd like to do a comparison between copying the arrays and swapping pointers.

Here is my code for it, the 2d arrays are n x n.

void swap_arrays(int n, float old[][n], float new_arr[][n]) {
    float temp[n][n];
    int arr_size = sizeof(float) * n * n;
    memcpy(temp, old, arr_size);
    memcpy(old, new_arr, arr_size);
    memcpy(new_arr, temp, arr_size);
}

It works fine for a 5 x 5 array, but it segfaults when the array is larger (the actual size I need is 4000+, it starts seg faulting at 2000+), at the first memcpy. Any help is appreciated.

like image 581
user5004049 Avatar asked Jan 07 '23 14:01

user5004049


2 Answers

It segfaults with 4000 but it's not memcpy()'s fault. It's because the size exceeds the stack size of your program.

Try to allocate the array dynamically and it should work fine, something like this

float *temp;
temp = malloc(sizeof(float) * n * n);
if (temp != NULL)
{
    /* memcpys here */
}

note that unlike the array, this cannot be accessed with two index notation, to achieve that you need something like

float **temp;
temp = malloc(sizeof(float *) * n);
for (size_t i = 0 ; i < n ; ++i)
    temp[i] = malloc(sizeof(float) * n); /* please check for `NULL' */

You will need free() in both cases, and in the second case your memcpy() will not work as it is. Because each element in temp is a pointer and not a float, so you need first to access the pointer and then copy the data with memcpy().

like image 134
Iharob Al Asimi Avatar answered Jan 10 '23 04:01

Iharob Al Asimi


Assuming that your problem is stack overflow caused by temp being too large, you can dynamically allocate the space. Since you are just memcpying you don't need to use a typed pointer:

void swap_arrays(int n, float old[n][n], float new[n][n])
{
    size_t sz = sizeof(float[n][n]);
    void *buf = malloc(sz);
    if ( !buf ) exit(EXIT_FAILURE);

    memcpy(buf, old, sz);
    memcpy(old, new, sz);
    memcpy(new, buf, sz);

    free(buf);
}

Of course, you may also have a stack overflow issue if you are writing float a[n][n]; in your calling code. You can get around that by using malloc too, e.g.:

float (*a)[n] = malloc(n * sizeof *a);
float (*b)[n] = malloc(n * sizeof *b);

If you use this latter approach then you can "swap" by swapping the pointers over, without having to copy all the data: void *tmp = a; a = b; b = tmp;

like image 28
M.M Avatar answered Jan 10 '23 05:01

M.M