mirror of
https://gitee.com/RubyMetric/chsrc.git
synced 2025-12-25 20:52:49 +00:00
Merge pull request #300 from Mikachu2333/fix/free_hwnd
处理 `xy.h` 内存以及部分资源未释放的问题
This commit is contained in:
commit
6060b325be
143
lib/xy.h
143
lib/xy.h
|
|
@ -23,7 +23,7 @@
|
||||||
#ifndef XY_H
|
#ifndef XY_H
|
||||||
#define XY_H
|
#define XY_H
|
||||||
|
|
||||||
#define _XY_Version "v0.2.1.0-2025/10/06"
|
#define _XY_Version "v0.2.1.1-2025/10/07"
|
||||||
#define _XY_Maintain_URL "https://github.com/RubyMetric/chsrc/blob/dev/lib/xy.h"
|
#define _XY_Maintain_URL "https://github.com/RubyMetric/chsrc/blob/dev/lib/xy.h"
|
||||||
#define _XY_Maintain_URL2 "https://gitee.com/RubyMetric/chsrc/blob/dev/lib/xy.h"
|
#define _XY_Maintain_URL2 "https://gitee.com/RubyMetric/chsrc/blob/dev/lib/xy.h"
|
||||||
|
|
||||||
|
|
@ -217,6 +217,27 @@ xy_malloc0 (size_t size)
|
||||||
* String
|
* String
|
||||||
******************************************************/
|
******************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 替换字符串指针并自动释放旧内存
|
||||||
|
*
|
||||||
|
* @param old_ptr 指向要被替换的字符串指针的指针 (char **)
|
||||||
|
* @param new_str 新的字符串指针
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
xy_ptr_replace (char **old_ptr, char *new_str)
|
||||||
|
{
|
||||||
|
if (old_ptr && *old_ptr)
|
||||||
|
{
|
||||||
|
char *temp = *old_ptr;
|
||||||
|
*old_ptr = new_str;
|
||||||
|
free (temp);
|
||||||
|
}
|
||||||
|
else if (old_ptr)
|
||||||
|
{
|
||||||
|
*old_ptr = new_str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 将 str 中所有的 pat 字符串替换成 replace,返回一个全新的字符串;也可用作删除、缩小、扩张
|
* @brief 将 str 中所有的 pat 字符串替换成 replace,返回一个全新的字符串;也可用作删除、缩小、扩张
|
||||||
*
|
*
|
||||||
|
|
@ -479,15 +500,15 @@ xy_streql (const char *str1, const char *str2)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
xy_streql_ic(const char *str1, const char *str2)
|
xy_streql_ic (const char *str1, const char *str2)
|
||||||
{
|
{
|
||||||
if (NULL == str1 || NULL == str2)
|
if (NULL == str1 || NULL == str2)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len1 = strlen(str1);
|
size_t len1 = strlen (str1);
|
||||||
size_t len2 = strlen(str2);
|
size_t len2 = strlen (str2);
|
||||||
if (len1 != len2)
|
if (len1 != len2)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -495,7 +516,7 @@ xy_streql_ic(const char *str1, const char *str2)
|
||||||
|
|
||||||
for (size_t i = 0; i < len1; i++)
|
for (size_t i = 0; i < len1; i++)
|
||||||
{
|
{
|
||||||
if (tolower(str1[i]) != tolower(str2[i]))
|
if (tolower (str1[i]) != tolower (str2[i]))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -569,14 +590,16 @@ xy_str_start_with (const char *str, const char *prefix)
|
||||||
static char *
|
static char *
|
||||||
xy_str_delete_prefix (const char *str, const char *prefix)
|
xy_str_delete_prefix (const char *str, const char *prefix)
|
||||||
{
|
{
|
||||||
char *new = xy_strdup (str);
|
|
||||||
bool yes = xy_str_start_with (str, prefix);
|
bool yes = xy_str_start_with (str, prefix);
|
||||||
if (!yes)
|
if (!yes)
|
||||||
return new;
|
{
|
||||||
|
return xy_strdup (str);
|
||||||
size_t len = strlen (prefix);
|
}
|
||||||
char *cur = new + len;
|
else
|
||||||
return cur;
|
{
|
||||||
|
size_t len = strlen (prefix);
|
||||||
|
return xy_strdup (str + len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -603,23 +626,26 @@ xy_str_delete_suffix (const char *str, const char *suffix)
|
||||||
static char *
|
static char *
|
||||||
xy_str_strip (const char *str)
|
xy_str_strip (const char *str)
|
||||||
{
|
{
|
||||||
char *new = xy_strdup (str);
|
if (!str)
|
||||||
|
xy_cant_be_null (str);
|
||||||
|
|
||||||
|
|
||||||
while (strchr ("\n\r\v\t\f ", new[0]))
|
const char *start = str;
|
||||||
{
|
while (*start && strchr ("\n\r\v\t\f ", *start))
|
||||||
new += 1;
|
start++;
|
||||||
}
|
|
||||||
|
|
||||||
size_t len = strlen (new);
|
if ('\0' == *start)
|
||||||
|
return xy_strdup ("");
|
||||||
|
|
||||||
char *last = new + len - 1;
|
const char *end = start + strlen (start) - 1;
|
||||||
|
while (end >= start && strchr ("\n\r\v\t\f ", *end))
|
||||||
|
end--;
|
||||||
|
|
||||||
while (strchr ("\n\r\v\t\f ", *last))
|
size_t len = (size_t) (end - start + 1);
|
||||||
{
|
char *ret = xy_malloc0 (len + 1);
|
||||||
*last = '\0';
|
memcpy (ret, start, len);
|
||||||
last -= 1;
|
ret[len] = '\0';
|
||||||
}
|
return ret;
|
||||||
return new;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
@ -733,7 +759,7 @@ xy_file_read (const char *path)
|
||||||
buf[read_bytes] = '\0';
|
buf[read_bytes] = '\0';
|
||||||
|
|
||||||
char *formatted_str = xy_str_gsub (buf, "\r\n", "\n");
|
char *formatted_str = xy_str_gsub (buf, "\r\n", "\n");
|
||||||
formatted_str = xy_str_gsub (formatted_str, "\r", "\n");
|
xy_ptr_replace (&formatted_str, xy_str_gsub (formatted_str, "\r", "\n"));
|
||||||
|
|
||||||
free (buf);
|
free (buf);
|
||||||
|
|
||||||
|
|
@ -1152,13 +1178,19 @@ _xy_win_powershellv5_profile ()
|
||||||
static bool
|
static bool
|
||||||
xy_file_exist (const char *path)
|
xy_file_exist (const char *path)
|
||||||
{
|
{
|
||||||
const char *new_path = path;
|
char *expanded_path = NULL;
|
||||||
|
const char *check_path = path;
|
||||||
|
|
||||||
if (xy_str_start_with (path, "~"))
|
if (xy_str_start_with (path, "~"))
|
||||||
{
|
{
|
||||||
new_path = xy_2strcat (xy_os_home, path + 1);
|
expanded_path = xy_2strcat (xy_os_home, path + 1);
|
||||||
|
check_path = expanded_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0 即 F_OK
|
// 0 即 F_OK
|
||||||
return (0==access (new_path, 0)) ? true : false;
|
bool result = (0 == access (check_path, 0)) ? true : false;
|
||||||
|
if (expanded_path) free (expanded_path);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1168,12 +1200,14 @@ xy_file_exist (const char *path)
|
||||||
static bool
|
static bool
|
||||||
xy_dir_exist (const char *path)
|
xy_dir_exist (const char *path)
|
||||||
{
|
{
|
||||||
|
char *allocated_dir = NULL;
|
||||||
const char *dir = path;
|
const char *dir = path;
|
||||||
if (xy.on_windows)
|
if (xy.on_windows)
|
||||||
{
|
{
|
||||||
if (xy_str_start_with (path, "~"))
|
if (xy_str_start_with (path, "~"))
|
||||||
{
|
{
|
||||||
dir = xy_2strcat (xy_os_home, path + 1);
|
allocated_dir = xy_2strcat (xy_os_home, path + 1);
|
||||||
|
dir = allocated_dir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1183,29 +1217,32 @@ xy_dir_exist (const char *path)
|
||||||
// 也可以用 opendir() #include <dirent.h>
|
// 也可以用 opendir() #include <dirent.h>
|
||||||
DWORD attr = GetFileAttributesA (dir);
|
DWORD attr = GetFileAttributesA (dir);
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
if (attr == INVALID_FILE_ATTRIBUTES)
|
||||||
{
|
{
|
||||||
// Q: 我们应该报错吗?
|
// Q: 我们应该报错吗?
|
||||||
return false;
|
result = false;
|
||||||
}
|
}
|
||||||
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
|
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
{
|
{
|
||||||
return true;
|
result = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
if (allocated_dir) free (allocated_dir);
|
||||||
|
return result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int status = system (xy_2strcat ("test -d ", dir));
|
char *tmp_cmd = xy_2strcat ("test -d ", dir);
|
||||||
|
int status = system (tmp_cmd);
|
||||||
if (0==status)
|
free (tmp_cmd);
|
||||||
return true;
|
bool result = (0==status);
|
||||||
else
|
if (allocated_dir) free (allocated_dir);
|
||||||
return false;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1228,13 +1265,17 @@ xy_normalize_path (const char *path)
|
||||||
|
|
||||||
if (xy_str_start_with (new, "~"))
|
if (xy_str_start_with (new, "~"))
|
||||||
{
|
{
|
||||||
new = xy_2strcat (xy_os_home, xy_str_delete_prefix (new, "~"));
|
char *tmp = xy_str_delete_prefix (new, "~");
|
||||||
|
char *joined = xy_2strcat (xy_os_home, tmp);
|
||||||
|
free (tmp);
|
||||||
|
xy_ptr_replace (&new, joined);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xy.on_windows)
|
if (xy.on_windows)
|
||||||
return xy_str_gsub (new, "/", "\\");
|
{
|
||||||
else
|
xy_ptr_replace (&new, xy_str_gsub (new, "/", "\\"));
|
||||||
return new;
|
}
|
||||||
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1251,10 +1292,10 @@ xy_parent_dir (const char *path)
|
||||||
char *dir = xy_normalize_path (path);
|
char *dir = xy_normalize_path (path);
|
||||||
|
|
||||||
/* 不管是否为Windows,全部统一使用 / 作为路径分隔符,方便后续处理 */
|
/* 不管是否为Windows,全部统一使用 / 作为路径分隔符,方便后续处理 */
|
||||||
dir = xy_str_gsub (dir, "\\", "/");
|
xy_ptr_replace (&dir, xy_str_gsub (dir, "\\", "/"));
|
||||||
|
|
||||||
if (xy_str_end_with (dir, "/"))
|
if (xy_str_end_with (dir, "/"))
|
||||||
dir = xy_str_delete_suffix (dir, "/");
|
xy_ptr_replace (&dir, xy_str_delete_suffix (dir, "/"));
|
||||||
|
|
||||||
char *last = NULL;
|
char *last = NULL;
|
||||||
|
|
||||||
|
|
@ -1268,9 +1309,10 @@ xy_parent_dir (const char *path)
|
||||||
|
|
||||||
/* Windows上重新使用 \ 作为路径分隔符 */
|
/* Windows上重新使用 \ 作为路径分隔符 */
|
||||||
if (xy.on_windows)
|
if (xy.on_windows)
|
||||||
return xy_str_gsub (dir, "/", "\\");
|
{
|
||||||
else
|
xy_ptr_replace (&dir, xy_str_gsub (dir, "/", "\\"));
|
||||||
return dir;
|
}
|
||||||
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1297,7 +1339,7 @@ xy_detect_os ()
|
||||||
if (fp)
|
if (fp)
|
||||||
{
|
{
|
||||||
char buf[256] = {0};
|
char buf[256] = {0};
|
||||||
fread (buf, 1, sizeof(buf) - 1, fp);
|
fread (buf, 1, sizeof (buf) - 1, fp);
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
if (strstr (buf, "Linux"))
|
if (strstr (buf, "Linux"))
|
||||||
{
|
{
|
||||||
|
|
@ -1332,9 +1374,10 @@ xy_detect_os ()
|
||||||
fp = popen ("uname -s", "r");
|
fp = popen ("uname -s", "r");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
{
|
{
|
||||||
if (opendir ("/etc/rc.d"))
|
DIR *bsd_dir = opendir ("/etc/rc.d");
|
||||||
|
if (bsd_dir)
|
||||||
{
|
{
|
||||||
closedir (d);
|
closedir (bsd_dir);
|
||||||
xy.on_bsd = true;
|
xy.on_bsd = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -863,6 +863,9 @@ measure_speed_for_every_source (Source_t sources[], int size, double speed_recor
|
||||||
char *curl_result = measure_speed_for_url (url);
|
char *curl_result = measure_speed_for_url (url);
|
||||||
double speed = parse_and_say_curl_result (curl_result);
|
double speed = parse_and_say_curl_result (curl_result);
|
||||||
speed_records[i] = speed;
|
speed_records[i] = speed;
|
||||||
|
|
||||||
|
/* 释放 url 内存 */
|
||||||
|
if (url) free (url);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1519,6 +1522,7 @@ chsrc_run_as_bash_file (const char *script_content)
|
||||||
char *cmd = xy_2strcat ("bash ", tmpfile);
|
char *cmd = xy_2strcat ("bash ", tmpfile);
|
||||||
chsrc_run (cmd, RunOpt_Dont_Abort_On_Failure);
|
chsrc_run (cmd, RunOpt_Dont_Abort_On_Failure);
|
||||||
remove (tmpfile);
|
remove (tmpfile);
|
||||||
|
free (tmpfile); /* 释放 tmpfile 路径内存 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1539,6 +1543,7 @@ chsrc_run_as_sh_file (const char *script_content)
|
||||||
char *cmd = xy_2strcat ("sh ", tmpfile);
|
char *cmd = xy_2strcat ("sh ", tmpfile);
|
||||||
chsrc_run (cmd, RunOpt_Dont_Abort_On_Failure);
|
chsrc_run (cmd, RunOpt_Dont_Abort_On_Failure);
|
||||||
remove (tmpfile);
|
remove (tmpfile);
|
||||||
|
free (tmpfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1558,6 +1563,7 @@ chsrc_run_as_pwsh_file (const char *script_content)
|
||||||
char *cmd = xy_2strcat ("pwsh ", tmpfile);
|
char *cmd = xy_2strcat ("pwsh ", tmpfile);
|
||||||
chsrc_run (cmd, RunOpt_Dont_Abort_On_Failure);
|
chsrc_run (cmd, RunOpt_Dont_Abort_On_Failure);
|
||||||
remove (tmpfile);
|
remove (tmpfile);
|
||||||
|
free (tmpfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1849,6 +1855,7 @@ chsrc_overwrite_file (const char *str, const char *filename)
|
||||||
size_t ret = fwrite (str, len, 1, f);
|
size_t ret = fwrite (str, len, 1, f);
|
||||||
if (ret != 1)
|
if (ret != 1)
|
||||||
{
|
{
|
||||||
|
fclose (f);
|
||||||
char *msg = ENGLISH ? xy_2strcat ("Write failed to ", file)
|
char *msg = ENGLISH ? xy_2strcat ("Write failed to ", file)
|
||||||
: xy_2strcat ("写入文件失败: ", file);
|
: xy_2strcat ("写入文件失败: ", file);
|
||||||
chsrc_error2 (msg);
|
chsrc_error2 (msg);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue