curl中有很多地方使用 strdup,但windows下已经废弃了“strdup”,而要求用 “_strdup” 替代 (
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strdup-wcsdup?view=vs-2019)。
这就是造成libcurl静态库调用free()时产生异常的原因。
其实 libcurl 已经考虑到不同平台下内存分配释放函数的差异,库实现中的malloc,calloc,strdup,free等函数,实际调用的是easy.c中定义的Curl_cmalloc,Curl_ccalloc,Curl_cstrdup,Curl_cfree 函数指针,初始化函数global_init()会定义这些函数指针。
/**
* curl_global_init() globally initializes curl given a bitwise set of the
* different features of what to initialize.
*/
static CURLcode global_init(long flags, bool memoryfuncs)
{
if(initialized++)
return CURLE_OK;
if(memoryfuncs) {
/* Setup the default memory functions here (again) */
Curl_cmalloc = (curl_malloc_callback)malloc;
Curl_cfree = (curl_free_callback)free;
Curl_crealloc = (curl_realloc_callback)realloc;
Curl_cstrdup = (curl_strdup_callback)system_strdup;
Curl_ccalloc = (curl_calloc_callback)calloc;
#if defined(WIN32) && defined(UNICODE)
Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
#endif
}
if(!Curl_ssl_init()) {
DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
goto fail;
}
#ifdef WIN32
if(Curl_win32_init(flags)) {
DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
goto fail;
}
#endif
其中,只有Curl_cstrdup的默认值比较特别,它指向 system_strdup 。可以看出,只有在_WIN32_WCE 定义的条件下 strdup指向 _strdup,否则调用curlx_strdup或strdup ,而由于config-win32.h中定义#define HAVE_STRDUP 1,所以用VS编译肯定不会用curlx_strdup,那就只有strdup了。
#if defined(_WIN32_WCE)
#define system_strdup _strdup
#elif !defined(HAVE_STRDUP)
#define system_strdup curlx_strdup
#else
#define system_strdup strdup
#endif
我们在这儿增加WIN32判断条件,这样在 visual studio下调用strdup的地方会指向我们期望的安全函数 _strdup。
- #if defined(_WIN32_WCE)
+ #if defined(_WIN32_WCE) || defined(_WIN32) ||defined(WIN32)
#define system_strdup _strdup
#elif !defined(HAVE_STRDUP)
#define system_strdup curlx_strdup
#else
#define system_strdup strdup
#endif