Reputation: 121
I wrote a little piece of code . I was playing with void * pointers in order to create a swap function for basic data types of C. I wrote two versions of this function , because strings are a bit different from the rest of the basic data types ( but maybe I'm wrong ) .The version of this function for int, float and char it works but a when I try to use the one for strings , Valgrind reports me multiple errors . Here's the main:
int main(){
int dimA=0,dimB=0;
char *v,*g,*str1="heygv",*str2="bag";
v=malloc(strlen(str1)+1);
strcpy(v,str1);
g=malloc(strlen(str2)+1);
strcpy(g,str2);
dimA=strlen(v);
dimB=strlen(g);
printf("\nX : %s %p ,Y : %s %p \n",v,v,g,g);
swapStr(v,g,dimA+1,dimB+1);
printf("\nX : %s %p ,Y : %s %p \n",v,v,g,g);
free(v);
free(g);
return 191;
}
Here's swap function,it works and swap correctly values of strings :
void* swapStr(void* a,void* b,int dimA,int dimB){
void* temp=malloc(dimA);
void* ptr;
memcpy(temp,a,dimA);
if(dimB>dimA){
ptr=realloc(a,dimB);
if(ptr==NULL){
printf("\nError 1 realloc in swapStr\n");
return;
}else a=ptr;
}
memcpy(a,b,dimB);
if(dimA>dimB){
ptr=realloc(b,dimA);
if(ptr==NULL){
printf("\nError 2 realloc in swapStr\n");
return;
}else b=ptr;
}
memcpy(b,temp,dimA);
free(temp);
temp=NULL;
}
And here ther's Valgrind's report:
X : heygv 0x51f2040 ,Y : bag 0x51f2090
--5756-- REDIR: 0x4ec9080 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x4a2472e (_vgnU_ifunc_wrapper)
--5756-- REDIR: 0x4ed1430 (libc.so.6:__memcpy_sse2_unaligned) redirected to 0x4c2e0d0 (memcpy@@GLIBC_2.14)
--5756-- REDIR: 0x4eb9ab0 (libc.so.6:realloc) redirected to 0x4c2ba52 (realloc)
--5756-- REDIR: 0x4eb8bb0 (libc.so.6:free) redirected to 0x4c2ac62 (free)
==5756== Invalid read of size 1
==5756== at 0x4E7EC15: vfprintf (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==5756== by 0x400885: main (swapVoid.c:46)
==5756== Address 0x51f2090 is 0 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756== Invalid read of size 1
==5756== at 0x4EAEBC1: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==5756== by 0x400885: main (swapVoid.c:46)
==5756== Address 0x51f2092 is 2 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756== Invalid read of size 1
==5756== at 0x4EAEBD4: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==5756== by 0x400885: main (swapVoid.c:46)
==5756== Address 0x51f2091 is 1 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756== Invalid read of size 1
==5756== at 0x4EC406B: __GI_mempcpy (in /usr/lib64/libc-2.20.so)
==5756== by 0x4EAEB0F: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==5756== by 0x400885: main (swapVoid.c:46)
==5756== Address 0x51f2090 is 0 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756== Invalid read of size 2
==5756== at 0x4EC407B: __GI_mempcpy (in /usr/lib64/libc-2.20.so)
==5756== by 0x4EAEB0F: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==5756== by 0x400885: main (swapVoid.c:46)
==5756== Address 0x51f2091 is 1 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
X : bag 0x51f2040 ,Y : bag 0x51f2090
==5756== Invalid free() / delete / delete[] / realloc()
==5756== at 0x4C2ACE9: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x40089D: main (swapVoid.c:49)
==5756== Address 0x51f2090 is 0 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756==
==5756== HEAP SUMMARY:
==5756== in use at exit: 6 bytes in 1 blocks
==5756== total heap usage: 4 allocs, 4 frees, 22 bytes allocated
==5756==
==5756== Searching for pointers to 1 not-freed blocks
==5756== Checked 65,256 bytes
==5756==
==5756== 6 bytes in 1 blocks are definitely lost in loss record 1 of 1
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756== LEAK SUMMARY:
==5756== definitely lost: 6 bytes in 1 blocks
==5756== indirectly lost: 0 bytes in 0 blocks
==5756== possibly lost: 0 bytes in 0 blocks
==5756== still reachable: 0 bytes in 0 blocks
==5756== suppressed: 0 bytes in 0 blocks
==5756==
==5756== ERROR SUMMARY: 11 errors from 7 contexts (suppressed: 0 from 0)
==5756==
==5756== 1 errors in context 1 of 7:
==5756== Invalid free() / delete / delete[] / realloc()
==5756== at 0x4C2ACE9: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x40089D: main (swapVoid.c:49)
==5756== Address 0x51f2090 is 0 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756==
==5756== 1 errors in context 2 of 7:
==5756== Invalid read of size 2
==5756== at 0x4EC407B: __GI_mempcpy (in /usr/lib64/libc-2.20.so)
==5756== by 0x4EAEB0F: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==5756== by 0x400885: main (swapVoid.c:46)
==5756== Address 0x51f2091 is 1 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756==
==5756== 1 errors in context 3 of 7:
==5756== Invalid read of size 1
==5756== at 0x4EC406B: __GI_mempcpy (in /usr/lib64/libc-2.20.so)
==5756== by 0x4EAEB0F: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==5756== by 0x400885: main (swapVoid.c:46)
==5756== Address 0x51f2090 is 0 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756==
==5756== 1 errors in context 4 of 7:
==5756== Invalid read of size 1
==5756== at 0x4EAEBC1: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==5756== by 0x400885: main (swapVoid.c:46)
==5756== Address 0x51f2092 is 2 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756==
==5756== 2 errors in context 5 of 7:
==5756== Invalid read of size 1
==5756== at 0x4EAEBD4: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==5756== by 0x400885: main (swapVoid.c:46)
==5756== Address 0x51f2091 is 1 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756==
==5756== 4 errors in context 6 of 7:
==5756== Invalid read of size 1
==5756== at 0x4E7EC15: vfprintf (in /usr/lib64/libc-2.20.so)
==5756== by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==5756== by 0x400885: main (swapVoid.c:46)
==5756== Address 0x51f2090 is 0 bytes inside a block of size 4 free'd
==5756== at 0x4C2BB1C: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==5756== by 0x400959: swapStr (swapVoid.c:77)
==5756== by 0x400860: main (swapVoid.c:45)
==5756==
==5756== ERROR SUMMARY: 11 errors from 7 contexts (suppressed: 0 from 0)
The errors seem to be linked to the wrong usage of free ()(or realloc ?) ,but why?Another strange fact Is that, If I run this program without valgrind ,it works , instead now you see that strings are not Correctly swapped.
Every possible suggestion is well accepted about how create a swap function that can swap ,at least ,basic data types.
Upvotes: 2
Views: 436
Reputation: 8674
You need to pass a pointer to your char*
into swapStr()
because if the pointer is reallocated, you need the string pointer (char*
) to point to the newly-allocated memory.
eg.
void* swapStr(char **ap,char** bp,int dimA,int dimB){
char *a = *ap;
char *b = *bp;
// ... rest of the function, including realloc
*ap = a;
*bp = b;
}
swapStr(&a, &b, dimA, dimB);
This ensures that if your a
or b
pointer was reallocated, the caller's pointer is also updated.
Prefer using correctly-typed pointers (char*
) rather than void*
when they are pointing to arrays of char
.
Upvotes: 5
Reputation: 34585
First the void*
function isn't returning a pointer (something the compiler should have warned you).
The main()
function does not know the pointers that were reallocated in swapStr()
swapStr(v,g,dimA+1,dimB+1);
printf("\nX : %s %p ,Y : %s %p \n",v,v,g,g);
Try with a double * pointers in the function
void swapStr(void **a, void **b, int dimA, int dimB)
...
swapStr(&v,&g,dimA+1,dimB+1);
so that the function can write the reallocated pointer values to the vars in main()
.
Lastly not all return paths free(temp)
. Here is a rehash of your code. I left left the function types as void**
because you want it to swap other data types too.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void fatal(char *msg) {
printf("%s\n", msg);
exit (1);
}
void swapStr(void **a, void **b, int dimA, int dimB){
void *temp = malloc(dimA);
if (temp == NULL)
fatal("Error allocating memory for temp\n");
memcpy(temp, *a, dimA);
if(dimB>dimA){
*a = realloc(*a, dimB);
if (*a == NULL)
fatal("Error reallocating memory for a\n");
}
if(dimA>dimB){
*b = realloc(*b, dimA);
if (*b == NULL)
fatal("Error reallocating memory for b\n");
}
memcpy(*a, *b, dimB);
memcpy(*b, temp, dimA);
free(temp);
}
int main(void){
int dimA=0, dimB=0;
char *str1="heygv", *str2="bag";
void *v, *g;
v = malloc(strlen(str1)+1);
if (v == NULL)
fatal("Error allocating memory for v\n");
strcpy(v, str1);
g = malloc(strlen(str2)+1);
if (g == NULL)
fatal("Error allocating memory for g\n");
strcpy(g, str2);
dimA = strlen(v);
dimB = strlen(g);
printf("\nX : %s %p ,Y : %s %p \n", (char*)v, v, (char*)g, g);
swapStr(&v, &g, dimA+1, dimB+1);
printf("\nX : %s %p ,Y : %s %p \n", (char*)v, v, (char*)g, g);
free(v);
free(g);
return 0;
}
Upvotes: 2