From 6df4a9a534248f82c274fd42caa64027cedb77a8 Mon Sep 17 00:00:00 2001 From: zsyg <3872006562@qq.com> Date: Sat, 28 Jun 2025 09:00:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=86=85=E5=AD=98=E9=94=BB?= =?UTF-8?q?=E7=82=BC=E5=99=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- others/C/memory/Makefile | 22 +++ others/C/memory/include/benchmark.h | 19 ++ others/C/memory/include/config.h | 22 +++ others/C/memory/include/error.h | 9 + others/C/memory/include/log.h | 21 +++ others/C/memory/include/memory_trainer.h | 54 ++++++ others/C/memory/include/utils.h | 15 ++ others/C/memory/memory_trainer.exe | Bin 0 -> 173897 bytes others/C/memory/src/benchmark.c | 40 +++++ others/C/memory/src/config.c | 29 +++ others/C/memory/src/error.c | 21 +++ others/C/memory/src/init.c | 24 +++ others/C/memory/src/log.c | 59 ++++++ others/C/memory/src/main.c | 219 +++++++++++++++++++++++ others/C/memory/src/memory_ops.c | 145 +++++++++++++++ others/C/memory/src/ui.c | 67 +++++++ others/C/memory/src/utils.c | 23 +++ others/C/memory/src/version.c | 11 ++ 18 files changed, 800 insertions(+) create mode 100644 others/C/memory/Makefile create mode 100644 others/C/memory/include/benchmark.h create mode 100644 others/C/memory/include/config.h create mode 100644 others/C/memory/include/error.h create mode 100644 others/C/memory/include/log.h create mode 100644 others/C/memory/include/memory_trainer.h create mode 100644 others/C/memory/include/utils.h create mode 100644 others/C/memory/memory_trainer.exe create mode 100644 others/C/memory/src/benchmark.c create mode 100644 others/C/memory/src/config.c create mode 100644 others/C/memory/src/error.c create mode 100644 others/C/memory/src/init.c create mode 100644 others/C/memory/src/log.c create mode 100644 others/C/memory/src/main.c create mode 100644 others/C/memory/src/memory_ops.c create mode 100644 others/C/memory/src/ui.c create mode 100644 others/C/memory/src/utils.c create mode 100644 others/C/memory/src/version.c diff --git a/others/C/memory/Makefile b/others/C/memory/Makefile new file mode 100644 index 0000000..ba3d4e4 --- /dev/null +++ b/others/C/memory/Makefile @@ -0,0 +1,22 @@ +CC = gcc +CFLAGS = -Wall -Wextra -I./include +LDFLAGS = -Wl,-subsystem,windows -municode -luser32 -lgdi32 -lcomctl32 -lpsapi +SRC = src/main.c src/memory_ops.c src/ui.c src/init.c \ + src/utils.c src/config.c src/benchmark.c src/log.c \ + src/error.c src/version.c +OBJ = $(SRC:.c=.o) +TARGET = memory_trainer.exe + +all: $(TARGET) + +$(TARGET): $(OBJ) + $(CC) $(CFLAGS) -o $(TARGET) $(OBJ) $(LDFLAGS) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + del /Q $(subst /,\,$(OBJ)) $(TARGET) + +.PHONY: all clean + diff --git a/others/C/memory/include/benchmark.h b/others/C/memory/include/benchmark.h new file mode 100644 index 0000000..d58b664 --- /dev/null +++ b/others/C/memory/include/benchmark.h @@ -0,0 +1,19 @@ +#ifndef BENCHMARK_H +#define BENCHMARK_H + +#include + +// 内存性能测试结果 +typedef struct { + double allocation_time; // 分配时间(ms) + double fill_time; // 填充时间(ms) + double free_time; // 释放时间(ms) +} BenchmarkResult; + +// 运行内存性能测试 +BenchmarkResult run_memory_benchmark(size_t size_mb); + +// 打印测试结果(支持中文) +void print_benchmark_result(const BenchmarkResult* result); + +#endif // BENCHMARK_H diff --git a/others/C/memory/include/config.h b/others/C/memory/include/config.h new file mode 100644 index 0000000..d4536ac --- /dev/null +++ b/others/C/memory/include/config.h @@ -0,0 +1,22 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#include + +// 内存训练器配置 +typedef struct { + size_t default_memory_size; // 默认内存大小(MB) + size_t max_memory_size; // 最大内存大小(MB) + int fill_mode; // 默认填充模式 +} Config; + +// 初始化配置 +void init_config(); + +// 获取当前配置 +Config* get_config(); + +// 保存配置到文件 +void save_config(); + +#endif // CONFIG_H diff --git a/others/C/memory/include/error.h b/others/C/memory/include/error.h new file mode 100644 index 0000000..f742a85 --- /dev/null +++ b/others/C/memory/include/error.h @@ -0,0 +1,9 @@ +#ifndef ERROR_H +#define ERROR_H + +#include "../include/memory_trainer.h" + +// 获取错误描述 +const wchar_t* get_error_message(ErrorCode code); + +#endif // ERROR_H diff --git a/others/C/memory/include/log.h b/others/C/memory/include/log.h new file mode 100644 index 0000000..21bee66 --- /dev/null +++ b/others/C/memory/include/log.h @@ -0,0 +1,21 @@ +#ifndef LOG_H +#define LOG_H + +#include +#include + +// 日志级别 +typedef enum { + LOG_DEBUG, + LOG_INFO, + LOG_WARNING, + LOG_ERROR +} LogLevel; + +// 初始化日志系统 +void init_logger(); + +// 记录日志(支持中文) +void log_message(LogLevel level, const wchar_t* format, ...); + +#endif // LOG_H diff --git a/others/C/memory/include/memory_trainer.h b/others/C/memory/include/memory_trainer.h new file mode 100644 index 0000000..b7a04e5 --- /dev/null +++ b/others/C/memory/include/memory_trainer.h @@ -0,0 +1,54 @@ +#ifndef MEMORY_TRAINER_H +#define MEMORY_TRAINER_H + +#include +#include + +// 错误代码定义 +typedef enum { + ERR_SUCCESS = 0, + ERR_ALLOCATION, + ERR_INVALID_PARAM, + ERR_SYSTEM +} ErrorCode; + +// 进度回调函数类型 +typedef void (*ProgressCallback)(int percent); + +// 内存操作函数声明 +void* allocate_memory(size_t size); +void fill_memory(void* ptr, size_t size, int mode, ProgressCallback callback); +void free_memory(void* ptr, size_t size); + +// 错误处理函数 +void report_error(ErrorCode code, const wchar_t* message); + +// 全局窗口句柄(外部声明) +extern HWND g_hMainWnd; + +// 进度回调函数 +void update_progress(int percent); + +// UI控件ID定义 +#define IDC_RUN_TEST 1001 +#define IDC_PROGRESS 1002 +#define IDC_RETAIN_MEM 1003 +#define IDC_FILL_ZERO 1004 +#define IDC_FILL_RANDOM 1005 + +// 窗口过程函数声明 +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + +// UI函数声明 +void init_main_window_ui(HWND hWnd); +LRESULT handle_ui_message(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + +// 初始化函数声明 +void initialize_application(HINSTANCE hInstance); +HINSTANCE get_app_instance(void); + +// 版本信息函数 +const wchar_t* get_version_string(void); +const wchar_t* get_build_date(void); + +#endif // MEMORY_TRAINER_H diff --git a/others/C/memory/include/utils.h b/others/C/memory/include/utils.h new file mode 100644 index 0000000..27fc9ed --- /dev/null +++ b/others/C/memory/include/utils.h @@ -0,0 +1,15 @@ +#ifndef UTILS_H +#define UTILS_H + +#include + +// 字节转换工具:MB转字节 +size_t mb_to_bytes(size_t mb); + +// 获取当前时间戳(毫秒) +long long get_timestamp(); + +// 打印调试信息(支持中文) +void debug_print(const wchar_t* message); + +#endif // UTILS_H diff --git a/others/C/memory/memory_trainer.exe b/others/C/memory/memory_trainer.exe new file mode 100644 index 0000000000000000000000000000000000000000..45b02170daf982f5ce0bd9d213de9b116d4b667a GIT binary patch literal 173897 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%0Dd5*To*x0OV*Z!*OO(Mg%@2mzwo-*{Sw)I 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 +#include + +// 运行内存性能测试 +BenchmarkResult run_memory_benchmark(size_t size_mb) { + BenchmarkResult result = {0}; + LARGE_INTEGER freq, start, end; + QueryPerformanceFrequency(&freq); + + // 测试内存分配 + QueryPerformanceCounter(&start); + void* ptr = allocate_memory(size_mb); + QueryPerformanceCounter(&end); + result.allocation_time = (end.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart; + + // 测试内存填充 + QueryPerformanceCounter(&start); + fill_memory(ptr, mb_to_bytes(size_mb), 0, NULL); + QueryPerformanceCounter(&end); + result.fill_time = (end.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart; + + // 测试内存释放 + QueryPerformanceCounter(&start); + free_memory(ptr, size_mb); + QueryPerformanceCounter(&end); + result.free_time = (end.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart; + + return result; +} + +// 打印测试结果(支持中文) +void print_benchmark_result(const BenchmarkResult* result) { + wprintf(L"=== 内存性能测试结果 ===\n"); + wprintf(L"分配时间: %.2f 毫秒\n", result->allocation_time); + wprintf(L"填充时间: %.2f 毫秒\n", result->fill_time); + wprintf(L"释放时间: %.2f 毫秒\n", result->free_time); +} diff --git a/others/C/memory/src/config.c b/others/C/memory/src/config.c new file mode 100644 index 0000000..0afe18b --- /dev/null +++ b/others/C/memory/src/config.c @@ -0,0 +1,29 @@ +#include "../include/config.h" +#include +#include + +// 全局配置实例 +static Config app_config = { + .default_memory_size = 100, // 默认100MB + .max_memory_size = 8192, // 最大8GB + .fill_mode = 0 // 默认填充0 +}; + +// 初始化配置 +void init_config() { + // TODO: 从文件加载配置 +} + +// 获取当前配置 +Config* get_config() { + return &app_config; +} + +// 保存配置到文件 +void save_config() { + FILE* fp = fopen("config.bin", "wb"); + if (fp) { + fwrite(&app_config, sizeof(Config), 1, fp); + fclose(fp); + } +} diff --git a/others/C/memory/src/error.c b/others/C/memory/src/error.c new file mode 100644 index 0000000..05a19d4 --- /dev/null +++ b/others/C/memory/src/error.c @@ -0,0 +1,21 @@ +#include "../include/memory_trainer.h" +#include "../include/log.h" +#include + +// 错误代码定义 +const wchar_t* error_messages[] = { + L"操作成功", + L"内存分配失败", + L"无效参数", + L"系统错误" +}; + + + +// 获取错误描述 +const wchar_t* get_error_message(ErrorCode code) { + if (code < 0 || code >= sizeof(error_messages)/sizeof(error_messages[0])) { + return L"未知错误"; + } + return error_messages[code]; +} diff --git a/others/C/memory/src/init.c b/others/C/memory/src/init.c new file mode 100644 index 0000000..fc46e30 --- /dev/null +++ b/others/C/memory/src/init.c @@ -0,0 +1,24 @@ +#include "../include/memory_trainer.h" +#include "../include/log.h" +#include + +// 初始化应用程序 +void initialize_application(HINSTANCE hInstance) { + // 初始化日志系统 + init_logger(); + + // 注册窗口类(Unicode版本) + WNDCLASSW wc = {0}; + wc.lpfnWndProc = WndProc; + wc.hInstance = hInstance; + wc.lpszClassName = L"MemoryTrainer"; + RegisterClassW(&wc); + + // 记录初始化完成 + log_message(LOG_INFO, L"应用程序初始化完成"); +} + +// 获取应用程序实例句柄 +HINSTANCE get_app_instance(void) { + return GetModuleHandleW(NULL); +} diff --git a/others/C/memory/src/log.c b/others/C/memory/src/log.c new file mode 100644 index 0000000..7d3735d --- /dev/null +++ b/others/C/memory/src/log.c @@ -0,0 +1,59 @@ +#include "../include/log.h" +#include "../include/memory_trainer.h" +#include "../include/error.h" +#include +#include +#include + +static FILE* log_file = NULL; +static LogLevel current_level = LOG_INFO; + +// 初始化日志系统 +void init_logger() { + log_file = _wfopen(L"memory_trainer.log", L"a, ccs=UTF-8"); + if (!log_file) { + log_file = stdout; + } +} + +// 记录日志(支持中文) +void log_message(LogLevel level, const wchar_t* format, ...) { + if (level < current_level) return; + + // 获取当前时间 + time_t now; + time(&now); + struct tm* tm_info = localtime(&now); + wchar_t time_buf[20]; + wcsftime(time_buf, 20, L"%Y-%m-%d %H:%M:%S", tm_info); + + // 格式化日志消息 + va_list args; + va_start(args, format); + fwprintf(log_file, L"[%s] ", time_buf); + vfwprintf(log_file, format, args); + fwprintf(log_file, L"\n"); + va_end(args); + + fflush(log_file); +} + +// 报告错误并显示给用户 +void report_error(ErrorCode code, const wchar_t* message) { + // 获取标准错误描述 + const wchar_t* error_desc = get_error_message(code); + + // 构建完整错误消息 + wchar_t full_msg[512]; + wsprintfW(full_msg, L"%s: %s", error_desc, message); + + // 记录到日志 + log_message(LOG_ERROR, L"错误代码 %d: %s", code, full_msg); + + // 显示给用户 + if (g_hMainWnd) { + MessageBoxW(g_hMainWnd, full_msg, L"内存锻炼器 - 错误", MB_ICONERROR); + } else { + OutputDebugStringW(full_msg); + } +} diff --git a/others/C/memory/src/main.c b/others/C/memory/src/main.c new file mode 100644 index 0000000..a82e0f3 --- /dev/null +++ b/others/C/memory/src/main.c @@ -0,0 +1,219 @@ +#define UNICODE +#define _UNICODE +#include +#include +#include +#include +#include +#include "../include/memory_trainer.h" + +// 全局变量 +HWND g_hMainWnd; +HWND hSizeEdit, hProgressBar, hRetainCheck, hRunButton; +HFONT hFont; + +// 初始化现代UI +void InitModernUI(HWND hWnd) { + // 创建字体 + hFont = CreateFont(16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, + DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + CLEARTYPE_QUALITY, DEFAULT_PITCH, L"微软雅黑"); + + // 内存大小输入 + CreateWindowW(L"STATIC", L"内存大小 (MB):", + WS_VISIBLE | WS_CHILD | SS_CENTERIMAGE, + 20, 20, 120, 30, hWnd, NULL, NULL, NULL); + + hSizeEdit = CreateWindowW(L"EDIT", L"100", + WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER, + 150, 20, 120, 30, hWnd, NULL, NULL, NULL); + + // 填充模式选择 + CreateWindowW(L"STATIC", L"填充模式:", + WS_VISIBLE | WS_CHILD | SS_CENTERIMAGE, + 20, 70, 120, 30, hWnd, NULL, NULL, NULL); + + HWND hFillZero = CreateWindowW(L"BUTTON", L"填充0", + WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | WS_GROUP, + 150, 70, 80, 30, hWnd, (HMENU)IDC_FILL_ZERO, NULL, NULL); + + CreateWindowW(L"BUTTON", L"随机填充", + WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON, + 240, 70, 100, 30, hWnd, (HMENU)IDC_FILL_RANDOM, NULL, NULL); + + SendMessage(hFillZero, BM_SETCHECK, BST_CHECKED, 0); + + // 进度条 + hProgressBar = CreateWindowW(PROGRESS_CLASSW, NULL, + WS_VISIBLE | WS_CHILD | PBS_SMOOTH, + 20, 120, 360, 30, hWnd, NULL, NULL, NULL); + SendMessage(hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); + + // 保持内存选项 + hRetainCheck = CreateWindowW(L"BUTTON", L"保持内存内容", + WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX, + 20, 170, 150, 30, hWnd, NULL, NULL, NULL); + + // 执行按钮 + hRunButton = CreateWindowW(L"BUTTON", L"开始测试", + WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 200, 170, 180, 40, hWnd, (HMENU)IDC_RUN_TEST, NULL, NULL); + + // 设置字体 + SendMessage(hSizeEdit, WM_SETFONT, (WPARAM)hFont, TRUE); + SendMessage(hRetainCheck, WM_SETFONT, (WPARAM)hFont, TRUE); + SendMessage(hRunButton, WM_SETFONT, (WPARAM)hFont, TRUE); +} + +// 主窗口过程 +LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) { + case WM_CREATE: + InitModernUI(hWnd); + break; + + case WM_COMMAND: + if (LOWORD(wParam) == IDC_RUN_TEST) { + wchar_t sizeText[32]; + GetWindowTextW(hSizeEdit, sizeText, 32); + int sizeMB = _wtoi(sizeText); + + // 获取系统内存信息 + MEMORYSTATUSEX memStatus; + memStatus.dwLength = sizeof(memStatus); + GlobalMemoryStatusEx(&memStatus); + + // 验证输入 + if (sizeMB <= 0) { + MessageBoxW(hWnd, L"请输入有效的内存大小(大于0)", L"错误", MB_ICONERROR); + return 0; + } + + // 检查是否超过系统可用内存的75% + DWORDLONG maxRecommended = memStatus.ullAvailPhys * 3 / 4; + if ((DWORDLONG)sizeMB * 1024 * 1024 > maxRecommended) { + wchar_t warning[256]; + wsprintfW(warning, L"请求的内存大小(%dMB)超过推荐值(%.1fMB)\n可能造成系统不稳定,是否继续?", + sizeMB, (float)maxRecommended/1024/1024); + if (MessageBoxW(hWnd, warning, L"警告", MB_YESNO | MB_ICONWARNING) != IDYES) { + return 0; + } + } + + // 获取填充模式 + int mode = 0; + if (SendMessage(GetDlgItem(hWnd, IDC_FILL_RANDOM), BM_GETCHECK, 0, 0) == BST_CHECKED) { + mode = 1; + } + + // MB转字节 + size_t bytes = 0; + if (sizeMB > 0 && sizeMB < 1024*1024) { // 限制最大1TB + bytes = (size_t)sizeMB * 1024 * 1024; + void* ptr = allocate_memory(bytes); + if (!ptr) { + // 错误信息已由report_error记录,直接返回 + return 0; + } + + // 显示分配成功 + SendMessage(hProgressBar, PBM_SETPOS, 10, 0); + + // 进度回调函数 + void progress_callback(int percent) { + PostMessage(g_hMainWnd, WM_APP, percent, 0); + } + + // 填充内存 + fill_memory(ptr, bytes, mode, progress_callback); + + // 检查填充是否完成 + if (SendMessage(hProgressBar, PBM_GETPOS, 0, 0) < 100) { + // 错误信息已由fill_memory中的report_error记录 + } + + // 确保完成 + SendMessage(hProgressBar, PBM_SETPOS, 100, 0); + PROCESS_MEMORY_COUNTERS_EX pmc; + GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)); + + wchar_t msg[256]; + wsprintfW(msg, L"成功填充 %d MB 内存\n实际使用: %.1f GB", + sizeMB, + (float)pmc.PrivateUsage / 1024.0f / 1024.0f / 1024.0f); + MessageBoxW(hWnd, msg, L"操作成功", MB_OK); + + if (SendMessage(hRetainCheck, BM_GETCHECK, 0, 0) != BST_CHECKED) { + free_memory(ptr, sizeMB); + } + } else { + MessageBoxW(hWnd, L"请输入有效的内存大小", L"错误", MB_ICONERROR); + } + } + break; + + case WM_APP: + SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)wParam, 0); + break; + + case WM_DESTROY: + DeleteObject(hFont); + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } + return 0; +} + +// 应用程序入口 +int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + PWSTR pCmdLine, int nCmdShow) { + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(pCmdLine); + // 调试输出 + OutputDebugStringW(L"内存锻炼器启动...\n"); + + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + wchar_t debugMsg[256]; + wsprintfW(debugMsg, L"处理器数量: %lu\n", (unsigned long)sysInfo.dwNumberOfProcessors); + OutputDebugStringW(debugMsg); + wsprintfW(debugMsg, L"页面大小: %lu\n", (unsigned long)sysInfo.dwPageSize); + OutputDebugStringW(debugMsg); + + MEMORYSTATUSEX memStatus; + memStatus.dwLength = sizeof(memStatus); + GlobalMemoryStatusEx(&memStatus); + wsprintfW(debugMsg, L"总物理内存: %.1f GB\n", (float)memStatus.ullTotalPhys/1024/1024/1024); + OutputDebugStringW(debugMsg); + // 注册窗口类 + WNDCLASSEX wc = {0}; + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wc.lpszClassName = L"MemoryTrainerModern"; + RegisterClassEx(&wc); + + // 创建主窗口 + g_hMainWnd = CreateWindowEx(0, L"MemoryTrainerModern", L"内存锻炼器", + WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, 450, 300, + NULL, NULL, hInstance, NULL); + + ShowWindow(g_hMainWnd, nCmdShow); + UpdateWindow(g_hMainWnd); + + // 消息循环 + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return (int)msg.wParam; +} diff --git a/others/C/memory/src/memory_ops.c b/others/C/memory/src/memory_ops.c new file mode 100644 index 0000000..ba8f7b3 --- /dev/null +++ b/others/C/memory/src/memory_ops.c @@ -0,0 +1,145 @@ +#include "../include/memory_trainer.h" +#include +#include +#include +#include + +// 分配指定大小的内存 +void* allocate_memory(size_t size_bytes) { + if (size_bytes == 0) { + report_error(ERR_INVALID_PARAM, L"无效的内存大小"); + return NULL; + } + + // 获取系统内存状态 + MEMORYSTATUSEX memStatus; + memStatus.dwLength = sizeof(memStatus); + GlobalMemoryStatusEx(&memStatus); + + // 统一debugMsg变量声明 + wchar_t debugMsg[512]; + + // 详细调试输出 + wsprintfW(debugMsg, L"开始内存分配...\n请求大小: %zu bytes (%.2f MB)\n系统总内存: %.2f GB\n可用内存: %.2f GB\n", + size_bytes, + (double)size_bytes / (1024 * 1024), + (double)memStatus.ullTotalPhys / (1024 * 1024 * 1024), + (double)memStatus.ullAvailPhys / (1024 * 1024 * 1024)); + OutputDebugStringW(debugMsg); + + // 分配并锁定内存(调整为系统页面大小的整数倍) + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + size_t actual_size = ((size_bytes + sysInfo.dwPageSize - 1) / sysInfo.dwPageSize) * sysInfo.dwPageSize; + + wsprintfW(debugMsg, L"实际分配大小: %zu bytes (%.2f MB), 页面大小: %lu\n", + actual_size, + (double)actual_size / (1024 * 1024), + sysInfo.dwPageSize); + OutputDebugStringW(debugMsg); + + void* ptr = VirtualAlloc(NULL, actual_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (!ptr) { + DWORD err = GetLastError(); + wsprintfW(debugMsg, L"内存分配失败,错误代码: %lu, 请求大小: %zu\n", err, actual_size); + OutputDebugStringW(debugMsg); + + LPWSTR errMsg = NULL; + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, err, 0, (LPWSTR)&errMsg, 0, NULL); + + wchar_t userMsg[512]; + wsprintfW(userMsg, L"内存分配失败(错误 %lu): %s", err, errMsg ? errMsg : L"未知错误"); + report_error(ERR_ALLOCATION, userMsg); + + if (errMsg) LocalFree(errMsg); + return NULL; + } + + wsprintfW(debugMsg, L"成功分配 %zu 字节内存,地址: %p\n", actual_size, ptr); + OutputDebugStringW(debugMsg); + + // 检查系统内存锁定限制 + SIZE_T minLock, maxLock; + GetProcessWorkingSetSize(GetCurrentProcess(), &minLock, &maxLock); + wsprintfW(debugMsg, L"进程工作集大小: 最小=%zu KB, 最大=%zu KB\n", + minLock/1024, maxLock/1024); + OutputDebugStringW(debugMsg); + + // 尝试锁定内存(限制锁定大小为工作集最大值的50%) + size_t lock_size = min(actual_size, maxLock/2); + if (!VirtualLock(ptr, lock_size)) { + DWORD err = GetLastError(); + wsprintfW(debugMsg, L"内存锁定失败,错误代码: %lu, 锁定大小: %zu MB\n", + err, lock_size/1024/1024); + OutputDebugStringW(debugMsg); + + // 使用系统错误代码继续执行 + report_error(ERR_SYSTEM, L"内存锁定部分失败,继续运行"); + } else { + wsprintfW(debugMsg, L"成功锁定 %zu MB 内存\n", lock_size/1024/1024); + OutputDebugStringW(debugMsg); + } + OutputDebugStringW(L"内存锁定成功\n"); + + // 写入所有页确保实际分配 + memset(ptr, 0, actual_size); + + return ptr; +} + +// 填充内存(带进度回调) +void fill_memory(void* ptr, size_t size_bytes, int mode, + ProgressCallback progress_callback) { + if (!ptr) { + report_error(ERR_INVALID_PARAM, L"空指针"); + return; + } + + // 验证内存范围 + MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery(ptr, &mbi, sizeof(mbi)) == 0) { + report_error(ERR_SYSTEM, L"内存查询失败"); + return; + } + + const size_t block_size = 1024 * 1024; // 1MB块 + size_t filled = 0; + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + + if (mode == 0) { // 填充0 + memset(ptr, 0, size_bytes); + if (progress_callback) progress_callback(100); + } else { // 填充随机值 + srand((unsigned)time(NULL)); + uint32_t* block = (uint32_t*)malloc(block_size); + + while (filled < size_bytes) { + size_t remaining = size_bytes - filled; + size_t current_block = remaining > block_size ? block_size : remaining; + + // 批量填充随机值 + for (size_t i = 0; i < current_block/sizeof(uint32_t); i++) { + block[i] = rand(); + } + memcpy((char*)ptr + filled, block, current_block); + + filled += current_block; + if (progress_callback) { + int percent = (int)(filled * 100 / size_bytes); + progress_callback(percent); + } + } + free(block); + } +} + +// 释放内存 +void free_memory(void* ptr, size_t size_bytes) { + if (ptr) { + size_t actual_size = size_bytes + 4096; + VirtualUnlock(ptr, actual_size); + VirtualFree(ptr, 0, MEM_RELEASE); + } +} diff --git a/others/C/memory/src/ui.c b/others/C/memory/src/ui.c new file mode 100644 index 0000000..a745442 --- /dev/null +++ b/others/C/memory/src/ui.c @@ -0,0 +1,67 @@ +#include "../include/memory_trainer.h" +#include +#include + +// 进度回调函数 +void update_progress(int percent) { + HWND hProgress = GetDlgItem(g_hMainWnd, IDC_PROGRESS); + if (hProgress) { + SendMessage(hProgress, PBM_SETPOS, percent, 0); + } +} + +// 初始化主窗口UI +void init_main_window_ui(HWND hWnd) { + g_hMainWnd = hWnd; + + // 创建内存大小输入框 + CreateWindowW(L"STATIC", L"内存大小(MB):", + WS_VISIBLE | WS_CHILD, + 20, 20, 100, 20, hWnd, NULL, NULL, NULL); + + CreateWindowW(L"EDIT", L"100", + WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER, + 130, 20, 80, 20, hWnd, NULL, NULL, NULL); + + // 创建填充模式单选按钮 + CreateWindowW(L"STATIC", L"填充模式:", + WS_VISIBLE | WS_CHILD, + 20, 50, 100, 20, hWnd, NULL, NULL, NULL); + + CreateWindowW(L"BUTTON", L"填充0", + WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | WS_GROUP, + 130, 50, 80, 20, hWnd, NULL, NULL, NULL); + + CreateWindowW(L"BUTTON", L"填充随机", + WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON, + 220, 50, 80, 20, hWnd, NULL, NULL, NULL); + + // 创建内存保持选项(更显眼的位置) + CreateWindowW(L"BUTTON", L"✔ 保持内存", + WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX, + 130, 80, 100, 20, hWnd, (HMENU)IDC_RETAIN_MEM, NULL, NULL); + + // 创建进度条(更显眼的位置和大小) + CreateWindowW(PROGRESS_CLASSW, NULL, + WS_VISIBLE | WS_CHILD | PBS_SMOOTH, + 20, 110, 360, 25, hWnd, (HMENU)IDC_PROGRESS, NULL, NULL); + SendDlgItemMessage(hWnd, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); + + // 创建操作按钮 + CreateWindowW(L"BUTTON", L"执行内存测试", + WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 20, 140, 280, 30, hWnd, (HMENU)IDC_RUN_TEST, NULL, NULL); +} + +// 处理UI消息 +LRESULT handle_ui_message(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CREATE: + init_main_window_ui(hWnd); + break; + + default: + return DefWindowProcW(hWnd, message, wParam, lParam); + } + return 0; +} diff --git a/others/C/memory/src/utils.c b/others/C/memory/src/utils.c new file mode 100644 index 0000000..1125bbd --- /dev/null +++ b/others/C/memory/src/utils.c @@ -0,0 +1,23 @@ +#include "../include/utils.h" +#include +#include + +// MB转字节 +size_t mb_to_bytes(size_t mb) { + return mb * 1024 * 1024; +} + +// 获取当前时间戳(毫秒) +long long get_timestamp() { + SYSTEMTIME st; + GetSystemTime(&st); + return (long long)st.wMilliseconds + + st.wSecond * 1000LL + + st.wMinute * 60000LL + + st.wHour * 3600000LL; +} + +// 打印调试信息(支持中文) +void debug_print(const wchar_t* message) { + wprintf(L"[DEBUG] %s\n", message); +} diff --git a/others/C/memory/src/version.c b/others/C/memory/src/version.c new file mode 100644 index 0000000..8d878d9 --- /dev/null +++ b/others/C/memory/src/version.c @@ -0,0 +1,11 @@ +#include "../include/memory_trainer.h" + +// 获取版本信息 +const wchar_t* get_version_string(void) { + return L"内存锻炼器 v1.0.0"; +} + +// 获取构建日期 +const wchar_t* get_build_date(void) { + return L"2025-06-01"; +}