C语言标准库函数返回指针不会造成内存泄漏吗?
我今天看C标准库时偶然发现几个函数是会返回字符串的,如:char*asctime(struct tm*timeptr);和char*ctime(time_t*timer);等等,它们返回的应该是局部指针变量,如果不释放是否会造成内存泄漏?
[解决办法]
返回的是个内部静态变量,非动态申请的,不会造成内存泄露
[解决办法]
首先可以肯定的是asctime函数返回指针指向的内存肯定不是使用malloc函数分配的,因为函数手册说明中没有说要使用free释放返回的指针,这个可以用linux下的man命令验证。
那么这个函数要么返回的是函数内部静态变量,要么是全局变量。很明显,这个函数是线程不安全的,在多线程同时调用时,会造成数据的被其他线程改变。
现在楼主说的函数基本都不怎么使用了,而使用最多的应该是其对应的线程安全版本:
char *asctime_r(const struct tm *tm, char *buf);
所以楼主说的函数可以不用关注了,类似返回指针的函数也可以不用关注了,主要关注其对应的线程安全版本就可以了。
[解决办法]
此函数在整个运行期都拥有那同一块内存,是固定的.你说会泄漏不?
[解决办法]
实际上,类似函数只有自己去查库函数手册。
某些垃圾的嵌入系统下,就必须自己去free的。
[解决办法]
查手册或标准文档。你的例子中的两个函数不用担心内存泄漏。
The array which holds this string is statically allocated and shared by both the ctime and asctime functions. Each time either one of these functions is called the content of this array is overwritten.
[解决办法]
要不要释放,看看标准库的说明就OK了。一般情况是不用释放的,但有个别还是需要的。
楼主说的这两个不需要。
[解决办法]
这个要看库函数是怎么实现的了,里面有没有用内存分配函数。对这种内存的使用策略,任何库都应该告知使用者详细情况,按照说明使用即可
[解决办法]
/***
*asctime.c - convert date/time structure to ASCII string
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Contains asctime() - convert a date/time structure to ASCII string.
*
*******************************************************************************/
#include <cruntime.h>
#include <time.h>
#include <internal.h>
#include <internal_securecrt.h>
#include <mtdll.h>
#include <malloc.h>
#include <stddef.h>
#include <tchar.h>
#include <dbgint.h>
#define _ASCBUFSIZE 26
static _TSCHAR buf[_ASCBUFSIZE];
/*
** This prototype must be local to this file since the procedure is static
*/
static _TSCHAR * __cdecl store_dt(_TSCHAR *, int);
static _TSCHAR * __cdecl store_dt (
REG1 _TSCHAR *p,
REG2 int val
)
{
*p++ = (_TSCHAR)(_T('0') + val / 10);
*p++ = (_TSCHAR)(_T('0') + val % 10);
return(p);
}
/***
*errno_t asctime_s(buffer, sizeInChars, time) - convert a structure time to
*ascii string
*
*Purpose:
* Converts a time stored in a struct tm to a charcater string.
* The string is always exactly 26 characters of the form
* Tue May 01 02:34:55 1984\n\0
*
*Entry:
* struct tm *time - ptr to time structure
* _TSCHAR *buffer - ptr to output buffer
* size_t sizeInChars - size of the buffer in characters including sapce for
* NULL terminator
*
*Exit:
* errno_t = 0 success
* out buffer with time string.
* errno_t = correct error code
* out buffer NULL terminated if it is at least 1 character in size
*
*Exceptions:
*
*******************************************************************************/
errno_t __cdecl _tasctime_s (
_TSCHAR *buffer,
size_t sizeInChars,
REG1 const struct tm *tb
)
{
REG2 _TSCHAR *p = buffer;
int day, mon;
int i;
_VALIDATE_RETURN_ERRCODE(
( buffer != NULL ) && ( sizeInChars > 0 ),
EINVAL
)
_RESET_STRING(buffer, sizeInChars);
_VALIDATE_RETURN_ERRCODE(
( sizeInChars >= _ASCBUFSIZE ),
EINVAL
)
_VALIDATE_RETURN_ERRCODE(
( tb != NULL ),
EINVAL
)
_VALIDATE_RETURN_ERRCODE(
( tb->tm_year >= 0 ),
EINVAL
)
// month 0 based
_VALIDATE_RETURN_ERRCODE(
( ( tb->tm_mon >= 0 ) && ( tb->tm_mon <= 11 ) ),
EINVAL
)
// hour/min/sec 0 based
_VALIDATE_RETURN_ERRCODE(
( ( tb->tm_hour >= 0 ) && ( tb->tm_hour <= 23 ) ),
EINVAL
)
_VALIDATE_RETURN_ERRCODE(
( ( tb->tm_min >= 0 ) && ( tb->tm_min <= 59 ) ),
EINVAL
)
_VALIDATE_RETURN_ERRCODE(
( ( tb->tm_sec >= 0 ) && ( tb->tm_sec <= 59 ) ),
EINVAL
)
// day 1 based
_VALIDATE_RETURN_ERRCODE(
(
( tb->tm_mday >= 1 ) &&
(
// Day is in valid range for the month
( ( _days[ tb->tm_mon + 1 ] - _days[ tb->tm_mon ] ) >=
tb->tm_mday )
[解决办法]
// Special case for Feb in a leap year
(
( IS_LEAP_YEAR( tb->tm_year + 1900 ) ) &&
( tb->tm_mon == 1 ) &&
( tb->tm_mday <= 29 )
)
)
),
EINVAL
)
// week day 0 based
_VALIDATE_RETURN_ERRCODE(
( ( tb->tm_wday >= 0 ) && ( tb->tm_wday <= 6 ) ),
EINVAL
)
/* copy day and month names into the buffer */
day = tb->tm_wday * 3; /* index to correct day string */
mon = tb->tm_mon * 3; /* index to correct month string */
for (i=0; i < 3; i++,p++) {
*p = *(__dnames + day + i);
*(p+4) = *(__mnames + mon + i);
}
*p = _T(' '); /* blank between day and month */
p += 4;
*p++ = _T(' ');
p = store_dt(p, tb->tm_mday); /* day of the month (1-31) */
*p++ = _T(' ');
p = store_dt(p, tb->tm_hour); /* hours (0-23) */
*p++ = _T(':');
p = store_dt(p, tb->tm_min); /* minutes (0-59) */
*p++ = _T(':');
p = store_dt(p, tb->tm_sec); /* seconds (0-59) */
*p++ = _T(' ');
p = store_dt(p, 19 + (tb->tm_year/100)); /* year (after 1900) */
p = store_dt(p, tb->tm_year%100);
*p++ = _T('\n');
*p = _T('\0');
return 0;
}
/***
*char *asctime(time) - convert a structure time to ascii string
*
*Purpose:
* Converts a time stored in a struct tm to a charcater string.
* The string is always exactly 26 characters of the form
* Tue May 01 02:34:55 1984\n\0
*
*Entry:
* struct tm *time - ptr to time structure
*
*Exit:
* returns pointer to static string with time string.
*
*Exceptions:
*
*******************************************************************************/
_TSCHAR * __cdecl _tasctime (
REG1 const struct tm *tb
)
{
REG2 _TSCHAR *p = buf;
errno_t e = 0;
_TSCHAR *retval; /* holds retval pointer */
_ptiddata ptd = _getptd_noexit();
/* Use per thread buffer area (malloc space, if necessary) */
if (ptd) {
#ifdef _UNICODE
if ( (ptd->_wasctimebuf != NULL)
[解决办法]
((ptd->_wasctimebuf =
(wchar_t *)_calloc_crt(_ASCBUFSIZE, sizeof(wchar_t))) != NULL) )
p = ptd->_wasctimebuf;
#else /* _UNICODE */
if ( (ptd->_asctimebuf != NULL)
------解决方案--------------------
((ptd->_asctimebuf =
(char *)_calloc_crt(_ASCBUFSIZE, sizeof(char))) != NULL) )
p = ptd->_asctimebuf;
#endif /* _UNICODE */
}
retval = p; /* save return value for later */
e = _tasctime_s( p, _ASCBUFSIZE, tb );
if ( e != 0 )
{
return NULL;
}
return (retval);
}
/***
*ctime.c - convert time argument to a string
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* contains _ctime32() - convert time value to string
*
*******************************************************************************/
#include <cruntime.h>
#include <time.h>
#include <internal.h>
#include <internal_securecrt.h>
#include <stddef.h>
#include <tchar.h>
/***
*errno_t _tctime32_s(buffer, sizeInChars, time) - converts a time stored as a __time32_t
*to a string
*
*Purpose:
* Converts a time stored as a __time32_t to a string of the form:
* Tue May 01 14:25:03 1984
*
*Entry:
* __time32_t *time - time value in XENIX format
*
*Exit:
* errno_t = 0 success
* buffer contains time converted to a string
* errno_t = correct error code
* buffer null terminated if it is at least 1 character in size
*
*Exceptions:
*
*******************************************************************************/
errno_t __cdecl _tctime32_s (
_TSCHAR * buffer,
size_t sizeInChars,
const __time32_t *timp
)
{
struct tm tmtemp;
errno_t e;
_VALIDATE_RETURN_ERRCODE(
( ( buffer != NULL ) && ( sizeInChars > 0 ) ),
EINVAL
)
_RESET_STRING(buffer, sizeInChars);
_VALIDATE_RETURN_ERRCODE( ( timp != NULL ), EINVAL )
_VALIDATE_RETURN_ERRCODE_NOEXC( ( *timp >= 0 ), EINVAL )
e = _localtime32_s(&tmtemp, timp);
if ( e == 0 )
{
e = _tasctime_s(buffer, sizeInChars, &tmtemp);
}
return e;
}
/***
*_TSCHAR *_tctime32(time) - converts a time stored as a __time32_t to a string
*
*Purpose:
* Converts a time stored as a __time32_t to a string of the form:
* Tue May 01 14:25:03 1984
*
*Entry:
* __time32_t *time - time value in XENIX format
*
*Exit:
* returns pointer to static string or NULL if time is before
* Jan 1 1980.
*
*Exceptions:
*
*******************************************************************************/
_TSCHAR * __cdecl _tctime32 (
const __time32_t *timp
)
{
struct tm tmtemp;
errno_t e;
_VALIDATE_RETURN( ( timp != NULL ), EINVAL, NULL )
_VALIDATE_RETURN_NOEXC( ( *timp >= 0 ), EINVAL, NULL )
e = _localtime32_s(&tmtemp, timp);
if ( e == 0 )
{
_BEGIN_SECURE_CRT_DEPRECATION_DISABLE
return(_tasctime(&tmtemp));
_END_SECURE_CRT_DEPRECATION_DISABLE
}
else
{
return(NULL);
}
}