【问题标题】:Errors using free() and realloc()使用 free() 和 realloc() 的错误
【发布时间】:2015-03-27 19:09:11
【问题描述】:

我写了一小段代码。我正在使用 void * 指针来为 C 的基本数据类型创建一个交换函数。我写了这个函数的两个版本,因为字符串与其他基本数据类型有点不同(但也许我错了) . 该函数的 int、float 和 char 版本可以正常工作,但是当我尝试将其用于字符串时,Valgrind 报告了多个错误。以下是主要内容:

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;

}

这是交换功能,它可以正确地交换字符串的值:

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;
}

这是 Valgrind 的报告:

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)

这些错误似乎与 free ()(或 realloc没有正确交换。

关于如何创建一个至少可以交换基本数据类型的交换函数的每一个可能的建议都被广泛接受。

【问题讨论】:

  • a=ptr;b=ptr; 不会更新原始指针。因为ab 是局部变量(只是指针的副本)。

标签: c memory-leaks valgrind memory-movement


【解决方案1】:

您需要将指向 char* 的指针传递给 swapStr(),因为如果重新分配指针,则需要字符串指针 (char*) 指向新分配的内存。

例如。

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);

这样可以确保如果您的 ab 指针被重新分配,调用者的指针也会被更新。


当它们指向char 的数组时,最好使用类型正确的指针 (char*) 而不是 void*

【讨论】:

    【解决方案2】:

    首先,void* 函数没有返回指针(编译器应该警告过你)。

    main() 函数不知道在swapStr() 中重新分配的指针

    swapStr(v,g,dimA+1,dimB+1);
    printf("\nX : %s %p ,Y : %s %p \n",v,v,g,g);
    

    尝试在函数中使用双 * 指针

    void swapStr(void **a, void **b, int dimA, int dimB)
    ...
    swapStr(&v,&g,dimA+1,dimB+1);
    

    以便函数可以将重新分配的指针值写入main() 中的变量。

    最后不是所有返回路径free(temp)。这是您的代码的重新散列。我将函数类型保留为void**,因为您也希望它交换其他数据类型。

    #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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-18
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 2012-07-13
      • 2020-09-27
      相关资源
      最近更新 更多