Как правильно использовать free с возвращенными указателями? - PullRequest
0 голосов
/ 31 мая 2018

Я написал небольшой пример задачи, чтобы узнать о распределении памяти и освобождении этой памяти (для защиты от утечек памяти):

#include <stdlib.h>

long* foo(char str[]) {
    long *nums;
    nums = calloc(2,sizeof(long));

    //something is happening depending on what's inside the char[]

    nums[0] = 57347534;
    nums[1] = 84757;

    return nums;
}

int main() {
    char str1[400] = "This is a test";

    long* retValue = foo(str1);

    //some lines of checking content of "retValue"

    char str2[400] = "This is another test";

    retValue = foo(str2);

    //some more lines of checking content of "retValue"

    char str3[400] = "This is a final test";

    retValue = foo(str3);

    //again some more lines of checking content of "retValue"

    free(retValue);
}

Итак, в моей функции main я использую три массива символовкоторый я перейду к моей функции.Эта функция имеет num указатель длинных значений, где я calloc два из них.Затем я просто вычисляю некоторые числа в соответствии с содержанием в str[] и возвращаю nums.

Мои вопросы по этому поводу:

  1. Как освободить память, которую я использовалдля nums?Потому что я не могу освободить его, прежде чем использовать его для возврата.
  2. Правильно ли освободить retValue в последней строке там?
  3. Прав ли я, что мне не нужно освобождать моймассивы символов, потому что они не являются динамическими?

Спасибо за ваши ответы, это помогло бы мне более безопасно использовать указатели!

Ответы [ 3 ]

0 голосов
/ 31 мая 2018

Если вы не хотите загромождать свой вызывающий код с помощью free, альтернатива - передать вызываемому массиву управляемый абонентом массив:

long foo(char str[], long *nums, int size) {
    if (size < 2) {  // passed array must be at least 2 long
        return -1;
    }

    //something is happening depending on whats inside the char[]

    nums[0] = 57347534;
    nums[1] = 84757;

    return 2;   // returns used size (or -1 for error)
}

int main() {
    long retValue[2];
    char str1[400] = "This is a test";

    if (-1 == foo(str1, retValue, 2)) {
        // process error condition
    }

    //some lines of checking content of "retValue"

    char str2[400] = "This is another test";

    if (-1 == foo(str2, retValue, 2)) {
        // process error condition
    }

    //some more lines of checking content of "retValue"

    char str3[400] = "This is a final test";

    if (-1 == foo(str3, retValue, 2)) {
        // process error condition
    }

    //again some more lines of checking content of "retValue"

    //free(retValue);  no need for free since nothing was allocated...

    return 0;
}
0 голосов
/ 31 мая 2018

Хороший способ ответить на вопросы о распределении и использовании памяти - использовать средство проверки памяти - я буду использовать Valgrind:

gcc-8 -std=c11 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds         50627661.c    -o 5062766

50627661.c: In function ‘foo’:
50627661.c:3:16: warning: unused parameter ‘str’ [-Wunused-parameter]
 long* foo(char str[]) {
           ~~~~~^~~~~
valgrind -q --leak-check=full ./50627661   

==14785== HEAP SUMMARY:
==14785==     in use at exit: 32 bytes in 2 blocks
==14785==   total heap usage: 3 allocs, 1 frees, 48 bytes allocated
==14785== 
==14785== 16 bytes in 1 blocks are definitely lost in loss record 1 of 2
==14785==    at 0x4C2EBA5: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14785==    by 0x10867F: foo (50627661.c:5)
==14785==    by 0x1086F6: main (50627661.c:18)
==14785== 
==14785== 16 bytes in 1 blocks are definitely lost in loss record 2 of 2
==14785==    at 0x4C2EBA5: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14785==    by 0x10867F: foo (50627661.c:5)
==14785==    by 0x108758: main (50627661.c:24)

Это показывает, что из трех выделенных ресурсов мыосвободил только одного из них - два других просочились.

0 голосов
/ 31 мая 2018

Вам необходимо вызывать free перед каждым новым назначением на retValue (если предыдущее назначение было от malloc, calloc или realloc).В противном случае у вас будут утечки памяти.

Каждому выделению должно соответствовать free, простое и простое.

...