Merge pull request #300 from Mikachu2333/fix/free_hwnd

处理 `xy.h` 内存以及部分资源未释放的问题
This commit is contained in:
曾奥然
2025-10-28 13:10:03 +08:00
committed by GitHub
2 changed files with 100 additions and 50 deletions

143
lib/xy.h
View File

@@ -23,7 +23,7 @@
#ifndef 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_URL2 "https://gitee.com/RubyMetric/chsrc/blob/dev/lib/xy.h"
@@ -217,6 +217,27 @@ xy_malloc0 (size_t size)
* 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返回一个全新的字符串也可用作删除、缩小、扩张
*
@@ -479,15 +500,15 @@ xy_streql (const char *str1, const char *str2)
}
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)
{
return false;
}
size_t len1 = strlen(str1);
size_t len2 = strlen(str2);
size_t len1 = strlen (str1);
size_t len2 = strlen (str2);
if (len1 != len2)
{
return false;
@@ -495,7 +516,7 @@ xy_streql_ic(const char *str1, const char *str2)
for (size_t i = 0; i < len1; i++)
{
if (tolower(str1[i]) != tolower(str2[i]))
if (tolower (str1[i]) != tolower (str2[i]))
{
return false;
}
@@ -569,14 +590,16 @@ xy_str_start_with (const char *str, const char *prefix)
static char *
xy_str_delete_prefix (const char *str, const char *prefix)
{
char *new = xy_strdup (str);
bool yes = xy_str_start_with (str, prefix);
if (!yes)
return new;
size_t len = strlen (prefix);
char *cur = new + len;
return cur;
{
return xy_strdup (str);
}
else
{
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 *
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]))
{
new += 1;
}
const char *start = str;
while (*start && strchr ("\n\r\v\t\f ", *start))
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))
{
*last = '\0';
last -= 1;
}
return new;
size_t len = (size_t) (end - start + 1);
char *ret = xy_malloc0 (len + 1);
memcpy (ret, start, len);
ret[len] = '\0';
return ret;
}
typedef struct
@@ -733,7 +759,7 @@ xy_file_read (const char *path)
buf[read_bytes] = '\0';
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);
@@ -1152,13 +1178,19 @@ _xy_win_powershellv5_profile ()
static bool
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, "~"))
{
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
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
xy_dir_exist (const char *path)
{
char *allocated_dir = NULL;
const char *dir = path;
if (xy.on_windows)
{
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>
DWORD attr = GetFileAttributesA (dir);
bool result = false;
if (attr == INVALID_FILE_ATTRIBUTES)
{
// Q: 我们应该报错吗?
return false;
result = false;
}
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
{
return true;
result = true;
}
else
{
return false;
result = false;
}
if (allocated_dir) free (allocated_dir);
return result;
#endif
}
else
{
int status = system (xy_2strcat ("test -d ", dir));
if (0==status)
return true;
else
return false;
char *tmp_cmd = xy_2strcat ("test -d ", dir);
int status = system (tmp_cmd);
free (tmp_cmd);
bool result = (0==status);
if (allocated_dir) free (allocated_dir);
return result;
}
return false;
@@ -1228,13 +1265,17 @@ xy_normalize_path (const char *path)
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)
return xy_str_gsub (new, "/", "\\");
else
return new;
{
xy_ptr_replace (&new, xy_str_gsub (new, "/", "\\"));
}
return new;
}
@@ -1251,10 +1292,10 @@ xy_parent_dir (const char *path)
char *dir = xy_normalize_path (path);
/* 不管是否为Windows全部统一使用 / 作为路径分隔符,方便后续处理 */
dir = xy_str_gsub (dir, "\\", "/");
xy_ptr_replace (&dir, xy_str_gsub (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;
@@ -1268,9 +1309,10 @@ xy_parent_dir (const char *path)
/* Windows上重新使用 \ 作为路径分隔符 */
if (xy.on_windows)
return xy_str_gsub (dir, "/", "\\");
else
return dir;
{
xy_ptr_replace (&dir, xy_str_gsub (dir, "/", "\\"));
}
return dir;
}
@@ -1297,7 +1339,7 @@ xy_detect_os ()
if (fp)
{
char buf[256] = {0};
fread (buf, 1, sizeof(buf) - 1, fp);
fread (buf, 1, sizeof (buf) - 1, fp);
fclose (fp);
if (strstr (buf, "Linux"))
{
@@ -1332,9 +1374,10 @@ xy_detect_os ()
fp = popen ("uname -s", "r");
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;
return;
}

View File

@@ -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);
double speed = parse_and_say_curl_result (curl_result);
speed_records[i] = speed;
/* 释放 url 内存 */
if (url) free (url);
}
else
{
@@ -1519,6 +1522,7 @@ chsrc_run_as_bash_file (const char *script_content)
char *cmd = xy_2strcat ("bash ", tmpfile);
chsrc_run (cmd, RunOpt_Dont_Abort_On_Failure);
remove (tmpfile);
free (tmpfile); /* 释放 tmpfile 路径内存 */
}
@@ -1539,6 +1543,7 @@ chsrc_run_as_sh_file (const char *script_content)
char *cmd = xy_2strcat ("sh ", tmpfile);
chsrc_run (cmd, RunOpt_Dont_Abort_On_Failure);
remove (tmpfile);
free (tmpfile);
}
@@ -1558,6 +1563,7 @@ chsrc_run_as_pwsh_file (const char *script_content)
char *cmd = xy_2strcat ("pwsh ", tmpfile);
chsrc_run (cmd, RunOpt_Dont_Abort_On_Failure);
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);
if (ret != 1)
{
fclose (f);
char *msg = ENGLISH ? xy_2strcat ("Write failed to ", file)
: xy_2strcat ("写入文件失败: ", file);
chsrc_error2 (msg);