简体   繁体   中英

How to swap memory between two void pointers in c

I am trying to swap the memory that is pointed to by two void pointers. I get an error because I can't do a sizeof on a void, or size of an element of pa or pb (because you can't dereference a void pointer). The problem is I can't determine what data type pa and pb are going to be at runtime(this is supposed to swap any data type sent as parameters). How would I determine that so I can properly use malloc? Here is my code:

void SwapObjects(void *pa, void *pb, size_t size)
{
    void *pc; 
    if ((pc = (malloc(size * sizeof(pa)) == NULL))) //this is wrong         {
        printf("Cannot allocate memory");
        return;
    }
    memcpy(pc, pa, size); //runtime error here
    memcpy(pa, pb, size);
    memcpy(pb, pc, size);
}

Your code is wrong because of parentheses

if ((pc = (malloc(size * sizeof(pa)) == NULL)))
/* ^^     ^---------------------------------^^^ 
 * ||________________________________________|| 
 * |__________________________________________|
 */

and as you see you are assigning the result of malloc(size * sizeof(pa)) == NULL to pc which is a pointer and that's of course, wrong.

It should be

if ((pc = malloc(size)) == NULL)

also you are allocating more memory than needed, trying to make your code compact doesn't make it better, you could have avoided all this by just doing this

pc = malloc(size);
if (pc == NULL)

it's clearer and will not cause the error.

If your code was to remain as is, you also need to free(pc) because other wise you will have a memory leak every time you call SwapObjects() .

Since they all are just pointers, you only need to reassign the pointers instead of unnecessarily copying the data

void SwapObjects(void **pa, void **pb)
{
    void *pc; 

    pc  = *pa;
    *pa = *pb;
    *pb = pc;
}

and then

SwapObjects(&pa, &pb);

will have the same effect without the memory leak in your code.

If you really need to swap the contents fix your code as explained above.

You could avoid using malloc() altogether

void SwapObjects(void *pa, void *pb, size_t size) {
    unsigned char tmp;
    unsigned char *a = pa, *b = pb;
    while(size--) {
        tmp = *a;
        *a++ = *b;
        *b++ = tmp;
        }
    }

I'm not completely sure I understand your intent.

  1. Do you want pointer A to reference pointer B's memory and vice versa? (Using your function signature):

     void SwapObjects( void *pa, void *pb ) { void *pTemp = pa; pa = pb; pb = pTemp; } 
  2. Do you want to copy the memory referenced by each pointer to the other's buffer?

    Note that there's no guarantee that this will work in the general case, because this function can't know the size of the pool referenced by each pointer--this information is not available to the programmer via any supported language construct in C. How the compiler keeps track of the size of the pool is up to the specific compiler, typically by storing information at a negative offset from the pointer address you have been given by malloc().

    So that means you will need to ask the caller to give your function buffer sizes that you must blindly trust (== unsafe!). You could be truncating data, or worse, reading past the end of valid data within a buffer, reading past the end of a buffer or writing past the end of a buffer. Unless this function can guarantee these buffer sizes (ie. the function itself allocates the buffers, or you have some form of strong contract with your callers) you should consider this code to be unsafe.

    The parameters sizeA and sizeB are assumed to be in bytes, not elements.

    Final point, don't forget to free() your malloc()'s!

     /* This function is unsafe! Buffer sizes are not validated */ void SwapOpbjects(void *pa, size_t sizeA, void *pb, size_t sizeB) { /* TODO: Ensure pa and pb are both non-NULL */ /* TODO: Ensure sizeA and sizeB are both > 0 */ void *pTemp = malloc( sizeA ); if( !pTemp ) { printf("malloc() failed!"); return; } memcpy( pTemp, pa, sizeA ); /* Safe, since we allocated pTemp ourselves */ memcpy( pa, pb, sizeB ); /* Unsafe! let's hope pa's pool is big enough to hold sizeB bytes; or you could risk truncating sizeB by only copying sizeA bytes... Neither choice is a great one */ memcpy( pb, pTemp, sizeA ); /* Unsafe! As per above. */ free( pTemp ); } 

Recommendation: stick with solution #1, or if that's not feasible, let us know use case so that the solutions can be best practices examples.

Good luck!

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