复制字符串-我该如何处理内存泄漏和错误情况?

时间:2019-01-12 15:52:01

标签: c pointers malloc

我正在尝试实现函数“ int * cpy_array(int v [],int size)”,该函数将数组复制到另一个数组中并返回新数组作为指针。我还必须提防错误情况并使用动态内存。

好吧,我知道当没有足够的可用内存时,malloc返回0。我想知道是否还有其他可能遗漏的错误。然后,无论成功还是错误,我都必须实现free()。 我试图实现类似的东西:

 if (!w[i]) { 
 for (k = 0; k < i; ++k)
 free(w[k]); 
 return 0;
}

但是总是有一个错误。 “在hot.c:2包含的文件中: C:/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/i686-w64-mingw32/include/stdlib.h:502:27:注意:预期为'void *',但参数为输入“ int””    void __cdecl free(void * _Memory);而且我不确定为什么要free()新数组还是应该释放旧数组?我试图在函数中使用指针释放它,但是两者都不起作用,也不认为它应该在主体中?

这是原始代码:

int *cpy_array(int v[], int size);

int main(void)
{
int size; 
size = 4;
int myArray[4] = {1234};
if (*cpy_array(myArray, size) == 0)
{
    printf("No memory available.");
}else{
printf("The new Array: %i", *cpy_array(myArray, size)); 
}

return 0;
}

 int *cpy_array(int v[], int size)
{
    int i;
    int *a  = malloc(size * sizeof(int));
    if(*a == 0)
    return 0;
    for (i = 0; i < size; i++)
    { 
        a[i] = v[i];
    }
return a;
}

3 个答案:

答案 0 :(得分:1)

在您的第一个代码段中,您错误地重新分配了整数数组w。您不能在该数组中释放单个整数,但是您只需输入:

free(w);

这将释放整个阵列。 您还可以从错误文本中看到-注意:预期为'void *',但参数的类型为'int'“ void __cdecl free(void * _Memory),该程序预期指向数组的指针而不是整数。

您不能释放旧数组,因为它是静态创建的,并且它的内存是在程序开始时分配的,并且它将在程序本身定义的函数的末尾释放,因此您不必为此担心。释放动态创建的数组(例如通过cpy_array(int v[], int size)函数创建的数组)是您的工作。

有关静态分配和动态分配之间的区别的更多信息,您可以在此处查找:

Difference between static memory allocation and dynamic memory allocation

这部分代码不会正确地打印数组(您将只打印数组的第一个数字),并且您将调用函数两次,这是多余的,对于同一数组只能执行一次

if (*cpy_array(myArray, size) == 0)
{
    printf("No memory available.");
}else{
    printf("The new Array: %i", *cpy_array(myArray, size)); 
}

您可以通过定义一个可以存储该函数返回值的指针来简化这些问题,因此不必调用两次,然后使用for循环正确打印该数组即可。

    int * copiedArray = cpy_array(myArray, size);
    if (copiedArray == NULL)
    {
        printf("No memory available.");
    }else{
        printf("The new Array: ");
        for (int i = 0; i < size; i++)
            printf("%i ", copiedArray[i]); 
    }

我注意到您正在检查指针是否指向某物。进入主程序:

if (*cpy_array(myArray, size) == 0)

然后进入cpy_array(int v[], int size)函数:

if(*a == 0)

这将不起作用,因为您正在取消引用指针并检查其指向的值是否为零。您要做的是检查指针本身的值。如果为NULL,则分配无效:

if (cpy_array(myArray, size) == NULL)

 if(a == NULL)

您应该使用NULL而不是零,因为您明确声明要检查指针的值,并且NULL可能不等于每台机器上的零。

有关此主题的更多信息:

What is the difference between NULL, '\0' and 0

答案 1 :(得分:0)

要检测与内存有关的问题,请使用 valgrind ,如果我这样做,则会给出:

 <Expander KeyboardNavigation.TabNavigation="None" IsExpanded="False" VerticalAlignment="Top" IsEnabled="True" ExpandDirection="Right" />

“有条件的跳转或移动取决于未初始化的值” 来自==10947== Memcheck, a memory error detector ==10947== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==10947== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==10947== Command: ./a.out ==10947== ==10947== Conditional jump or move depends on uninitialised value(s) ==10947== at 0x10548: cpy_array (c.c:25) ==10947== by 0x104B3: main (c.c:11) ==10947== ==10947== Invalid read of size 4 ==10947== at 0x104B8: main (c.c:11) ==10947== Address 0x0 is not stack'd, malloc'd or (recently) free'd ==10947== ==10947== ==10947== Process terminating with default action of signal 11 (SIGSEGV) ==10947== Access not within mapped region at address 0x0 ==10947== at 0x104B8: main (c.c:11) ==10947== If you believe this happened as a result of a stack ==10947== overflow in your program's main thread (unlikely but ==10947== possible), you can try to increase the size of the ==10947== main thread stack using the --main-stacksize= flag. ==10947== The main thread stack size used in this run was 8388608. ==10947== ==10947== HEAP SUMMARY: ==10947== in use at exit: 16 bytes in 1 blocks ==10947== total heap usage: 1 allocs, 0 frees, 16 bytes allocated ==10947== ==10947== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==10947== at 0x4847568: malloc (vg_replace_malloc.c:299) ==10947== by 0x10533: cpy_array (c.c:24) ==10947== by 0x104B3: main (c.c:11) ==10947== ==10947== LEAK SUMMARY: ==10947== definitely lost: 16 bytes in 1 blocks ==10947== indirectly lost: 0 bytes in 0 blocks ==10947== possibly lost: 0 bytes in 0 blocks ==10947== still reachable: 0 bytes in 0 blocks ==10947== suppressed: 0 bytes in 0 blocks ==10947== ==10947== For counts of detected and suppressed errors, rerun with: -v ==10947== Use --track-origins=yes to see where uninitialised values come from ==10947== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 6 from 3) 中的*a“大小为4的无效读取。 ”。是因为if(*a == 0)

使您取消引用了0

return 0;更改为if(*a == 0)以解决先前的两个问题,即条件(先验)为假,_valgrind说:

if(a == 0)

所以是的,您有内存泄漏,因为丢失了==11116== Memcheck, a memory error detector ==11116== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==11116== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==11116== Command: ./a.out ==11116== Mein neuer Array enthaelt folgende Zeichen: 1==11116== ==11116== HEAP SUMMARY: ==11116== in use at exit: 32 bytes in 2 blocks ==11116== total heap usage: 3 allocs, 1 frees, 1,056 bytes allocated ==11116== ==11116== 16 bytes in 1 blocks are definitely lost in loss record 1 of 2 ==11116== at 0x4847568: malloc (vg_replace_malloc.c:299) ==11116== by 0x10523: cpy_array (c.c:24) ==11116== by 0x104A3: main (c.c:11) ==11116== ==11116== 16 bytes in 1 blocks are definitely lost in loss record 2 of 2 ==11116== at 0x4847568: malloc (vg_replace_malloc.c:299) ==11116== by 0x10523: cpy_array (c.c:24) ==11116== by 0x104CF: main (c.c:15) ==11116== ==11116== LEAK SUMMARY: ==11116== definitely lost: 32 bytes in 2 blocks ==11116== indirectly lost: 0 bytes in 0 blocks ==11116== possibly lost: 0 bytes in 0 blocks ==11116== still reachable: 0 bytes in 0 blocks ==11116== suppressed: 0 bytes in 0 blocks ==11116== ==11116== For counts of detected and suppressed errors, rerun with: -v ==11116== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 3) 的分配返回的2倍

您需要输入类似以下内容:

cpy_array

进行校正 valgrind 不会发出任何信号:

int * v = cpy_array(myArray, size);

if (*v == 0)
{
  printf("Speicher kann nicht freigegeben werden.");
}else{
  printf("Mein neuer Array enthaelt folgende Zeichen: %i", 
   *v);    
}

free(v);

我鼓励你

  • 编译所有警告检测,例如valgrind --leak-check=full ./a.out ==11224== Memcheck, a memory error detector ==11224== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==11224== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==11224== Command: ./a.out ==11224== Mein neuer Array enthaelt folgende Zeichen: 1==11224== ==11224== HEAP SUMMARY: ==11224== in use at exit: 0 bytes in 0 blocks ==11224== total heap usage: 2 allocs, 2 frees, 1,040 bytes allocated ==11224== ==11224== All heap blocks were freed -- no leaks are possible ==11224== ==11224== For counts of detected and suppressed errors, rerun with: -v ==11224== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
  • 遇到问题时,请使用 valgrind 和/或调试器
  • 即使您在 valgrind 下也看不到问题,所以问题可以隐藏

答案 2 :(得分:0)

这不是初始化数组的正确方法

int myArray[4] = {1234};

int myArray[4] = { 1,2,3,4 };

或者简单地

int myArray[] = { 1,2,3,4 };

编写时调用函数cpy_array ..

if (*cpy_array(myArray, size) == 0)   

不正确,为什么?因为如果该函数返回NULL,那么您将取消引用NULL


在函数cpy_array中,您取消引用a,这是不正确的,而是比较指针

if ( a == NULL)

,并且将标准常量NULL用于空指针而不是0,因为在所有平台上它可能都不是0。