2011-02-03 5 views
1

Можно ли вернуть массив, созданный динамически (используя malloc) внутри функции обратно к вызывающему?Возвращение массива символов из функции в c

Я знаю, что возвращение статически выделенного массива неверно, потому что стек отключается, когда функция возвращается, а переменная перестает быть действительной, но как насчет динамически распределенной переменной?

+0

Вы можете вернуть указатель, или там что-то более сложное, что вы имели в виду? – Swiss

+3

Статическое распределение! = Автоматическое распределение. Локальные переменные имеют автоматическую продолжительность хранения. Статическая продолжительность хранения означает, что объект существует в течение всего времени работы программы (эти объекты объявляются либо в области файла, либо с использованием 'static' в функции). –

+0

Нет, это то, что я хотел сделать. – theReverseFlick

ответ

5

Возврат всего, что выделяется с помощью malloc, прекрасен, если тот, кто использует вашу функцию, заботится о свободном() при его завершении. malloc выделяет кучу, которая по сути является глобальной в вашей программе.

+0

В конце концов, именно так работает 'malloc()'. – caf

+0

Если я не освобожу что-то, что я выделил, используя «malloc», и программа завершается, тогда память освобождается сама по себе? – theReverseFlick

+0

@ShyamLovesToCode: Да, если ваша ОС (или что-то близкое к ней) не работает, она будет освобождена. Тем не менее, «опрятно» освобождает материал, который вы используете вручную. –

0

Да, вы можете. Просто malloc() массив внутри вашей функции и верните указатель.

НО, вызывающий должен понять, что в какой-то момент его нужно освободить, или у вас будет утечка памяти.

0

Вы можете, конечно, вернуть массив, выделенный с помощью malloc, но вы должны убедиться, что вызывающий объект в конечном итоге освобождает массив с помощью free; если вы не освободите массив malloc ', память останется «в использовании» до выхода программы.

3

Как уже отмечалось, на самом деле вы можете вернуть указатель на символ. Однако другой распространенный метод заключается в том, чтобы вызывающий передал указатель для заполнения метода вместе с параметром длины. Это делает так, чтобы функция, ответственная за выделение памяти, также была той же функцией, ответственной за освобождение памяти, которая может облегчить просмотр утечек памяти. Это такие функции, как snprintf и strncpy.

/* Performs a reverse strcpy. Returns number of bytes written if dst is 
* large enough, or the negative number of bytes that would have been 
* written if dst is too small too hold the copy. */ 
int rev_strcpy(char *dst, const char *src, unsigned int dst_len) { 
    unsigned int src_len = strlen(src); /* assumes src is in fact NULL-terminated */ 
    int i,j; 

    if (src_len+1 > dst_len) { 
     return -(src_len+1); /* +1 for terminating NULL */ 
    } 

    i = 0; 
    j = src_len-1; 
    while (i < src_len) { 
     dst[i] = src[j]; 
     ++i; 
     ++j; 
    } 
    dst[src_len] = '\0'; 

    return src_len; 
} 

void random_function() { 
    unsigned int buf_len; 
    char *buf; 
    int len; 
    const char *str = "abcdefg"; 

    buf_len = 4; 
    buf = malloc(buf_len * sizeof(char)); 
    if (!buf) { 
     /* fail hard, log, whatever you want */ 
     return; 
    } 

    /* ...whatever randomness this function needs to do */ 

    len = rev_strcpy(buf, str, buf_len); 
    if (len < 0) { 
     /* realloc buf to be large enough and try again */ 
     free(buf); 
     buf_len = -len; 
     buf = malloc(buf_len * sizeof(buf)); 
     if (!buf) { 
      /* fail hard, log, whatever you want */ 
      return; 
     } 
     len = rev_strcpy(buf, str, sizeof(buf)); 
    } 

    /* ... the rest of the randomness this function needs to do */ 

    /* random_function has allocated the memory, random_function frees the memory */ 
    free(buf); 
} 

Это может привести к некоторым накладным расходам, хотя, если вы не знаете, как большой буфер вам нужно, и нужны вызвать функцию дважды, но часто вызывающие имеют хорошее представление о том, как большая потребности буфера быть. Также для этого требуется немного больше логики, чтобы гарантировать, что функция не переполняет данный буфер. Но он несет ответственность за освобождение памяти тем, что выделяет память, а также позволяет передавать локальную стек памяти.

Пример только возвращая char*:

/* Performs a reverse strcpy. Returns char buffer holding reverse copy of 
* src, or NULL if memory could not be allocated. Caller is responsible 
* to free memory. */ 
char* rev_strcpy(const char *src) { 
    unsigned int src_len = strlen(src); /* assumes src is in fact NULL-terminated */ 
    char *dst; 
    int i,j; 

    dst = malloc((src_len+1) * sizeof(char)); 
    if (!dst) { 
     return NULL; 
    } 

    i = 0; 
    j = src_len-1; 
    while (i < src_len) { 
     dst[i] = src[j]; 
     ++i; 
     ++j; 
    } 
    dst[src_len] = '\0'; 

    return dst; 
} 

void random_function() { 
    char *buf; 
    const char *str = "abcdefg"; 

    /* ...whatever randomness this function needs to do */ 

    buf = rev_strcpy(str);   
    if (!buf) { 
     /* fail hard, log, whatever you want */ 
     return; 
    } 

    /* ... the rest of the randomness this function needs to do */ 

    /* random_function frees the memory that was allocated by rev_strcpy */ 
    free(buf); 
} 
Смежные вопросы