Self-Deleting Executables

文档信息抽取技术:从非结构化文本到结构化信息的旅程 文档信息抽取技术是一种将非结构化文本转化为结构化信息的技术。这种技术可以从各类文档中自动提取出如实体、关系和其他重要信息,并将它们转化为方便计算机进一步处理和分析的格式。 阅读详情
 

This is a subject that tends to come up every so often in the newsgroups, so I thought I'd write an article about the techniques I've collected to enable an executable to delete itself from disk (whilst running, that is). There is very little information on the web, and what information exists is also hard to find.

Why would you want a program to delete itself? The only good reason I know of is an un-install program that needs to remove an application, as well as itself in order to completely remove the application from disk. I'm sure there are other good reasons for self-deleting executables, but un-installation is probably the most common.

I know many different methods, each of which I will describe shortly. I must take this opportunity to mention that only one of these techniques has been developed by myself. Apart from the last method, I am presenting the same material described by Jeffrey Richter in his January 1996 MSJ column, titled "Win32 Q&A". Click here to read the original article. The rest of the techniques were originally developed by Gary Nebbett - or heavily influenced by his work. So, I hope no-one thinks I am ripping off other people's ideas because all these techniques have existed for years before I encountered them.

There used to be two methods for a program to delete itself - actually doing it from the same program, and forcing a separate program to do it on your behalf. When Windows XP came out the "self-deleting" executable became a part of history - it is no longer possible for a Windows program (which runs on any version of Windows) to delete itself. However there are lots of techniques which can achieve the same effect - the ones I know about are listed below.

Why the obvious doesn't work

If you try to run the following code, nothing will happen.

TCHAR szFilePath[_MAX_PATH];

// Get current executable path
GetModuleFileName(NULL, szFilePath, _MAX_PATH);

// Delete specified file
DeleteFile(szFilePath);

The code above retrieves the full path to the current executable, and then tries to delete the file whilst running. This code will fail - because all 32bit versions of Windows (95, 98, ME, NT, 2000, XP etc) use a mechanism called memory-mapped files to load an executable image into memory.

When the Windows loader runs an executable, it opens the executable's disk file and maps that region of disk into memory, effectively loading the executable into memory. This disk file is kept open during the lifetime of the process, and is only closed when the process terminates. Because of this lock on the file, it is normally impossible to delete an executable file whilst it is running. Just run notepad.exe, then try to delete the notepad executable - it won't work.

The MoveFileEx method

I'm going to mention this technique even though it doesn't really solve our problem, because it is quite useful to know and can be handy in other situations.

MoveFileEx(szExistingFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); 

The MoveFileEx API moves a file to a new location. When you pass NULL as the second parameter, this causes the file to be moved "nowhere", effectively deleting the file. Now, ordinarily this would fail if you tried this with the path to the current executable. However, if we specify MOVEFILE_DELAY_UNTIL_REBOOT in the dwFlags parameter, this tells Windows not to move (or delete) the file until the system is shutdown or rebooted.

There are a few problems with this technique. Firstly, you cannot remove the directory that the executable resides in. Second, the file is not deleted immediately - if your system doesn't get rebooted very often, then the file will stay around. But the biggest problem is that MoveFileEx is not implemented on Windows 95/98/ME. Today this is not really a problem and the MoveFileEx is the neatest, safest way for a program to delete itself.

The WININIT.INI method

Under Windows 95/98/ME, an application called WININIT.EXE runs each time the system is started. This application looks for a file called WININIT.INI. If this file exists, WININIT.EXE looks for a section called [Rename]. Each entry in the [Rename] section specifies a file rename operation which will occur (once) when time the system starts. This method is obviously very similar to the MoveFileEx method described above.

[Rename]
NUL=c:/dir/myapp.exe
c:/dir/new.exe=c:/dir/old.exe

The filename to the left of the equal sign specifies the new name of the filename on the right. When NUL is used as the new filename, the file is deleted. This means that an application can write an entry into WININIT.INI, specifying NUL and the applications own full path.

You must be careful when writing an entry to the [Rename] section. You cannot use WritePrivateProfileString API call, because this function prevents any duplicate entries from occuring under the same section. This restriction would prevent there from being more than one "NUL=" entry. Therefore you must manually write any entry if you want to use this technique.

The Self-Deleting Batch File method

This is quite a well known method, and was documented in MSDN some time ago. This technique works on both Windows 95 and Windows NT. It works because MS-DOS batch files are able to delete themselves. To test this technique, create a small batch file containing the single command:

del %0.bat

The batch file, when run, deletes itself and issues an error "The batch file cannot be found". This error is just a simple message, so it can be safely ignored. By itself this isn't too useful, but when modified to delete our executable it solves our problem, albeit in a rather forceful manner. Our executable will create a batch file (called C:/DelUs.bat) with the following content:

:Repeat
del "C:/MYDIR/MYPROG.EXE"
if exist "MYPROG.EXE" goto Repeat
rmdir "C:/MYDIR"
del "/DelUS.bat"

This batch file repeatedly attempts to delete the specified file, and will run continuously consuming CPU until it succeeds. When the execuable has been deleted, the batch file then deletes itself.

The executable needs to spawn off the batch file using CreateProcess, and then should exit immediately. It would be a good idea to give the batch file's thread of execution a low priority so that it doesn't get much execution time until the original executable has terminated.

The sourcecode download at the top of this article contains the full code to this technique.

The COMSPEC method

This is a method kindly shared by Tony Varnas, who recently emailed me this snippet:

BOOL SelfDelete()
{
TCHAR szFile[MAX_PATH], szCmd[MAX_PATH];

if((GetModuleFileName(0,szFile,MAX_PATH)!=0) &&
(GetShortPathName(szFile,szFile,MAX_PATH)!=0))
{
lstrcpy(szCmd,"/c del ");
lstrcat(szCmd,szFile);
lstrcat(szCmd," >> NUL");

if((GetEnvironmentVariable("ComSpec",szFile,MAX_PATH)!=0) &&
((INT)ShellExecute(0,0,szFile,szCmd,0,SW_HIDE)>32))
return TRUE;
}
return FALSE;
}

This method is very similar to the batch-file method (above) but is alot neater in its implementation. It works under all 32bit versions of Windows (95,98,ME,NT,2000,XP), as long as the COMSPEC environment variable is defined. This is always defined (by default) to be the full path to the operating system's command interpreter. For Windows 95, this is "command.exe". For Windows NT, this is "cmd.exe".

The function will only work if the executable has exited, so it is important to call this function and then exit immediately. It works by spawning a copy of the system's command interpreter, and asking it to perform. the following command:

del exepath >> NUL

This deletes the current executable, and pipes the output to NUL (no output). The shell process is created with a hidden window as well, so the whole process is invisible.

The DELETE_ON_CLOSE method

The CreateFile API call accepts several flags which affect how a file is created or opened. One of these flags, FILE_FLAG_DELETE_ON_CLOSE, specifies that the file will be deleted when the last handle to it is closed. The basis to this technique will be to run an executable with this flag set, so that when it exits, it is deleted automatically.

The first step is to create an empty file with the DELETE_ON_CLOSE flag specified. The exact binary content of the current executable file is then copied into this new file, in effect duplicating the executable on disk. A new process is then created (using the new executable file). This has the effect that the duplicate file's handle count is incremented. Also, when the new process was created, the full path of the current process was passed through the command-line argument.

Next, the current executable (which wants to delete itself) closes the file handle used to create the new process, and then exits. Now, the duplicate's file-handle count is decremented, but because CreateProcess incremented its handle count when it started, the file is not deleted.

At this point, the duplicate executable has started running. The PID specified on the command-line is used to open a handle to the original process. The duplicate waits for the original process to terminate, using WaitForSingleObject. When this call returns, the duplicate can call DeleteFile on the filename also specified through its command-line argument. The original executable (the one that wanted to delete itself) has been successfully deleted. This just leaves the duplicate copy, which exits normally. The duplicate's file-handle count drops to zero, the DELETE_ON_CLOSE flag comes into effect, and the duplicate file is deleted also.

It sounds a bit complicated, but it's not too difficult. Here's the steps one more time:

[ Current process ]
1. Create a new file with FILE_FLAG_DELETE_ON_CLOSE.
2. Copy the current executable's content into the new file.
3. Create a new process with the duplicate executable:
4. Pass the current executable's full path and PID in the call to CreateFile.
5. Sleep for a short time to give the new process time to start.
6. Close the new file.
7. Exit current process.

[ Duplicate process ]
8. Wait for the process specified on command-line to die.
9. Delete file specified on command-line.
10. Exit duplicate process.

There are just a couple of technicalities to mention. First, when the "new" process is spawned, the "old" process must sleep for a short period, enough to let the Windows loader open the file and create the process (thus incrementing it's file count).

Second, the new process must wait until the old process terminates, which releases its file count.

Third, when the duplicate executable is created, it must also have the FILE_SHARE_DELETE flag specified, otherwise CreateProcess will fail, because it won't be able to open the file whilst we have it open with the DELETE_ON_CLOSE flag set.

Obviously this method will require careful coding, because the program must be written in such a way so that it can perform. these dual tasks. The "new" executable must know that it's job is to delete the file specified on the command line, for instance.

It's a little messy, but it does work very well. In fact, the uninstall program that I wrote, which is included with the software you can download from this site, uses this very method. I've included an example program which demonstrates this technique.

An alternative method is to write a very small stand-alone executable, which it's sole task is to delete the file-name specified on it's command-line. This executable could then be imbedded as a "payload" to the executable which wants to delete itself. This payload would be created and executed in the same way as described above.

The Ultimate Self-Deleting Executable!

This inline assembly snippet is short and simple. I can't claim credit for this code - I found it posted on usenet some time ago. The author's name is Gary Nebbett, author of "Windows NT Native API Reference". Actually this technique was first published in Windows Developer Journal around 1996.

#include <windows.h>

int main(int argc, char *argv[])
{
char buf[MAX_PATH];
HMODULE module;

module = GetModuleHandle(0);
GetModuleFileName(module, buf, MAX_PATH);
CloseHandle((HANDLE)4);

__asm
{
lea eax, buf
push 0
push 0
push eax
push ExitProcess
push module
push DeleteFile
push UnmapViewOfFile
ret
}

return 0;
}

This snippet ONLY works under Windows NT and 2000. As soon as you compile and run the above program, it just disappears from disk! It works because under NT and 2000 the OS keeps a usermode HANDLE reference to the memory-mapped file which backs the executable image on disk. This HANDLE always has a value of "4" under these OSs.

Unfortunately this gem only works under NT/2000, not XP or .NET Server. This is because these OSs no longer maintain a usermode HANDLE to the executable's memory-mapped file - this section object is only accessible in kernel using a pointer reference. So although this technique is incredibly slick (it is the only true self-deleting method) it is no longer as-is.

Now for Windows 9x!

Thanks must go to Tony Varnas again for some great detective work. He managed to unearth the following assembler snippet which works exactly like the snippet above, but this time for Windows 95,98,ME (tested on all three).

#include <windows.h>

int main(int argc, char *argv[])
{
char buf[MAX_PATH];
HMODULE module;

module = GetModuleHandle(0);
GetModuleFileName(module, buf, MAX_PATH);

__asm
{
lea eax, buf
push 0
push 0
push eax
push ExitProcess
push module
push DeleteFile
push FreeLibrary
ret
}

return 0;
}

Solution for XP+

After the original self-deleting technique Gary Nebbett posted a solution on Jan 19 2002 which works for XP. The following code should be packaged as a DLL which is callable from RunDLL32. The idea is that an external program (RunDLL32) is used which first waits for the original executable to finish. The DLL which is loaded into RunDLL then performs the original self-deleting trick. This is possible because the kernel maintains references to DLLs differently to the main executable.

#include <windows.h> 

#pragma comment(linker, "-export:CleanupA=_CleanupA@16?)

extern "C" void CALLBACK CleanupA(HWND, HINSTANCE, PSTR, int)
{
static MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(&mbi, &mbi, sizeof mbi);
PVOID module = mbi.AllocationBase;

CHAR buf[MAX_PATH];
GetModuleFileName(HMODULE(module), buf, sizeof buf);

__asm
{
lea eax, buf
push 0
push 0
push eax
push ExitProcess
push module
push DeleteFile
push FreeLibrary
ret
}
}

The idea that an external program could be used to self-delete it's parent is what influenced me to develop the following technique which works for all versions of Windows, but does not require a separate DLL which is dropped to disk.

The Definitive Self Deleting Executablenew

I am pleased to present what I believe is the definitive self-deleting executable, for all versions of Windows.

Now this technique is complicated so I won't include the code here - please get it from the sourcecode zipfile (selfdel05.c). Instead I will describe how it works and the issues involved.

  • Firstly a child process is created in a suspended state (any process will do - i.e. explorer.exe).
  • Some code is then injected into the address-space of the child process.
  • The injected code waits for the parent-process to exit.
  • The parent-process is then deleted.
  • The injected code then calls ExitProcess, which terminates the child process.

The neat thing about this technique is that the spawned child process never really executes (no windows ever appear) - only the "self-deleting" code in the child gets to execute. After the parent process terminates and is deleted, the child process terminates using ExitProcess, preventing anything further from happening. Effectively an arbitrary child-process is hijacked and coerced into deleting it's parent.

My first version of this technique (inside selfdelxp.c) used CreateRemoteThread to inject the code into the suspended child process. This was quite neat because the child never ran - only the injected thread with the self-deleting code ever executed. The downside to this technique is that it only ran on Windows-NT based platforms.

The latest version (selfdel05.c) does not use CreateRemoteThread to inject code into the child. It therefore works on all versions of Windows. The self-deleting code is injected into the spawned child by hijacking the primary thread of the process. The thread's stack is manipulated in such a way so that space is "allocated" on the stack - into which the self-deleting code is written. The instruction-pointer for the thread is then altered so that it points to the injected code on the thread's stack. When the child process (and primary thread) is resumed the code executes right off the stack, deleting the parent process, and then exits.

There are issues involved with this last technique. The first is the injection of code into an already running thread - this is not a desirable thing to do, but because the thread's "real" execution is never resumed (the process exits as soon as the parent is deleted) it seems like a viable way to do this.

The second issue involves the Win32 environment. When a child process is created in a suspended state the program has not started executing yet - there is still alot of Win32 environment setup that must be performed before the entry-point to the executable is called. So when we hijack this thread to do our bidding, we are doing so in an environment that is not yet fully initialized, and is not ready for Win32 API calls (it is still mid-way through executing some internel part of the OS!). The API calls that are made (WaitForSingleObject, DeleteFile etc) do however work - but this is not guaranteed in furture OS releases.

The exact same issue exists when you CreateRemoteThread into a process that was started as suspended - the OS hasn't yet finished intializing your process's environment before the remote thread starts to execute. This is why alot of Win32 API calls will fail (such as RemoveDirectory).

Conclusion

I've used this article to describe all the methods I know of to delete an executable whilst it is running. You can take your pick of the techniques, but the last method presented is currently the only one which works well for all versions of Windows.

Cursor概述及环境配置 Cursor 是一款基于 AI 的代码编辑器,支持 VS Code 配置迁移和 Java 开发环境配置。主要功能分为 Cursor Settings(AI 相关设置)和 Editor Settings(基础编辑器设置)。用户可通过一键导入或手动方式迁移 VS Code 配置,配置包括主题、扩展和快捷键等。对于 Java 开发,需配置 JDK 和 Maven 路径,并安装 Java 扩展插件以获得完整开发体验,如代码补全、调试和 Maven 项目管理。此外,Cursor 支持汉化配置,用户可安装中文语言包切换 阅读详情

相关推荐

ESP32小车DIY:从零搭建无线遥控智能车(附完整代码与避坑指南)

本文详细介绍了如何从零开始DIY一台基于ESP32的无线遥控智能小车。内容涵盖核心硬件选型、电路设计、低延迟ESP-NOW无线通信协议的配置与实战,以及双电机差速控制算法与PWM调速的实现。文章提供了完整的代码示例和关键的避坑指南,旨在帮助开发者快速构建稳定可靠的智能车平台,并为进一步的功能扩展奠定基础。

gamma的博客 471

Failed to resolve:问题的解决方法

构建项目的时候出现了这个异常。 解决办法1:修改项目下的的bulid.gradle文件,添加maven { url 'https://jitpack.io' }即可: allprojects { repositories { google() jcenter() maven { url 'https://jitpack.io' } ...

HelloWorld的专栏 1万+

GD32模拟IIC读写DVC1124

GD32模拟IIC读写集澈AFE芯片DVC1124

ponyma_的博客 1227

执行文件的自删除

Self-deleting Executables Techniques which allow an executable file to delete itself whilst running This is a subject that tends to come up every so often in the newsgroups,

liu_cheng_ran的专栏 1358

Win11系统重装全记录:从备份Office激活到搞定RAID阵列,我的微星笔记本复活记

本文详细记录了Win11系统重装的完整过程,从数据备份到RAID阵列配置,特别针对微星笔记本的特殊硬件驱动问题提供了解决方案。文章涵盖了Office激活状态备份、BIOS设置、驱动安装顺序等关键步骤,帮助用户顺利完成系统重装并优化性能。

weixin_31421613的博客 312

SkyWalking跨线程Trace传递实战:手把手教你用RunnableWrapper解决异步链路中断问题

本文深入解析了SkyWalking在异步编程场景下链路追踪中断的根源,并提供了使用RunnableWrapper等官方包装类的实战解决方案。通过详细的原理解析和代码示例,手把手指导开发者如何实现跨线程的Trace传递,确保分布式系统监控链路的完整性,有效解决异步任务导致的链路中断问题。

sand8的博客 495

Failed to resolve。。问题原因

Android Studio3.1.4    Failed to resolve: com.github.joyrun.ActivityRouter:router:0.3.5 之所以出现Failed to resolve。。。。可以考虑是仓库的问题     这样改下:将 maven { url "https://dl.google.com/dl/android/maven2/" }...

m0_37271466的博客 5557

【机器视觉】Halcon 最新版本安装教程(HALCON 24.11.1.1 Progress-Steady)

注:如果使用评估版本,下载前先了解最新评估授权密钥所支持的版本。。近几年不同版本安装过程类似,均可参考本教程。

OpenSeek的博客 3万+

shell,chapter 2

Advanced Bash-Scripting Guide: Prev Next Chapter 2. Starting Off With a Sha-Bang Shell programming is a 1950s juke box . . . --Larry Wall Table of Co...

weixin_30642029的博客 146

黑猫详解【UFS Unipro】第1篇:Unipro协议框架详解

UniPro规范适用于广泛的设备类型,如应用程序处理器、co-处理器、调制解调器、存储子系统,包括非易失性内存模块、显示器、相机传感器、3D图形和多媒体加速器。它还适用于不同类型的数据流量,如控制消息、批量数据传输和分组流。MIPI UniPro是一个成熟的通用接口,易于实现、可在传统模块化设备架构中灵活使用,适合满足并应对移动和其他行业不断增长的需求。UniPro充当UFS的数据链路层,负责host和device的连接。UniPro不仅定义了数据链路层,它本是也是一个比较完整的协议栈。

黑猫奥利奥的博客 3645

Python 爬虫实战:Boss直聘 Python 岗位招聘数据爬取

本文介绍了一个Python爬虫项目,用于抓取Boss直聘平台的Python岗位招聘数据并进行可视化分析。项目采用requests库发送POST请求,通过抓包分析获取JSON接口,绕过HTML解析直接获取结构化数据。主要内容包括: 接口分析:找到关键POST接口,解析请求头和JSON参数格式 环境准备:安装requests/pandas/matplotlib/pyecharts等依赖库 核心实现: 手动获取登录Cookie 构建请求头和城市代码映射 实现分页抓取职位列表数据 项目特色在于直接解析JSON接口而

u014481728的博客 298

关于Linux下gcc 编译 C 源文件时,生成的是Shared object file而不是Executable file

最近在Debian下写C时,发现用readelf命令查看编译后的可执行文件类型时,发现文件类型是DYN (Shared object file),而不是EXEC (Executable file)。 -&amp;gt; % readelf -h a.out ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Cl...

czw 1万+

YOLOv11模型改进-模块-引入特征细化模块FRFN 解决小目标、遮挡等问题

FRFN 是一种专门设计的深度学习结构,旨在提高图像处理任务中的特征表示能力。它的核心设计理念是通过逐层细化和优化特征图,从而实现更高的分类和检测精度。1. 特征提取层:通过卷积层提取初始特征,并进行批量归一化以增强稳定性。2. 特征细化模块:在每个模块中,当前层特征图与前一层特征图进行融合,以强化特征表示。3. 跳跃连接:通过跳跃连接保留多尺度信息,帮助缓解深层网络中的信息丢失。4. 非线性激活:使用激活函数(如ReLU)增加模型的非线性能力。5. 输出层。

qq_64693987的博客 3337

通过SP_Flash_Tool线刷失败解决方法

Error 5054 Message:  BROM ERROR S_DL_GET_DRAM_SETTINGS_FAIL (5054)  Meaning: The files you're trying to flash do not belong to or are not compatible with the phone you're trying to flash the

时光 7万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

关于FLASH player DEBUGGER LOGGER 输出的一个问题

flash player debugger11.2 在C:\Documents and Settings\a501279\Application Data\Macromedia\Flash Player\Logs 下的flashlog.txt 无法输出 GOOLE了一下,国外朋友的发现如下: 解决方法: 把mm.cfg放在%HOMEDRIVE%%HOMEPATH%下, echo %HOME

zjhgx的专栏 2060

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

关于Failed to resolve的问题解决

为了帮你快速解决问题,直接帮你连接到本人的以下文章,请直接参考以下文章。 Failed to resolve问题解决办法

qq_43276983的博客 1万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

微软ping程序源代码完整版

微软ping程序源代码完整版作者:侯志江编写自己的一个ping程序,可以说是许多人迈出网络编程的第一步吧!!这个ping程序的源代码经过我的修改和调试,基本上可以取代windows中自带的ping程序. 各个模块后都有我的详细注释和修改日志,希望能够对大家的学习有所帮助!!/*  本程序的主要源代码来自MSDN网站, 笔者只是做了一些改进和注释! 另外需要注意的是在Build之前,必须

1934

VUE基础语法

vue基础语法:首先做的是创建一个js文件,vue.js(官网学习教程里有),此文件和一下各个文件在同一级目录:/*! * Vue.js v2.5.16 * (c) 2014-2018 Evan You * Released under the MIT License. */ (function (global, factory) { typeof exports === 'object...

gaston的博客 1万+

Failed to resolve问题的解决

问题:今天在引入GreenDao的DaoSample时,总是会出现Failed to resolve包的问题。 最后经大神解救,发现是需要在build.gradle里面添加如下代码,表示所有都依赖这两个库:allprojects { repositories { jcenter() google() } }

l317118524的博客 1万+

CVI 键盘输入信息读取记录TXT

如何用文本文件记录键盘按键及时间信息。如下: 声明一个文件句柄: static int gLogFile = 0;   复制代码 程序开始时初始化它: gLogFile = OpenFile("d:\\TestLog.txt",VAL_READ_WRITE,VAL_APPEND,VAL_ASCII); 复制代码

思维逆逝 4247

循环嵌套(多层 for 循环)

表:order(订单表,order_id, user_id)、user(用户表,user_id, user_name)✅ 优化:先查所有订单,拿到所有 user_id 批量 in 查询,内存 join。✅ 优化:先把优惠券转 HashMap,单层循环查找(hash 查找 O (1))SQL 只有 2 次,O (1) 数据库查询,内存遍历 O (n)。需求:查询所有订单列表,同时带出每个订单对应的用户名称。需求:订单列表、优惠券列表,把订单匹配对应的优惠券名称。复杂度:O (M+N),非常快。

weixin_43732943的博客 222

Python+Agent入门笔记(六):记忆和状态,从“一次性问答”到“能用助手”

滑动窗口的缺点很明显:被扔掉的信息就真没了。如果用户第一轮说“我不吃辣”,隔了二十轮让他推荐餐厅,模型已经忘了。定期把旧的对话压缩成一段总结,作为一条特殊的消息插进去。"""把除 system 和最近 keep_recent 条以外的消息,压缩成一条摘要。返回新的 messages 列表。"""# 把旧消息拼成纯文本,让模型总结content = f"[工具结果]把除 system 和最近 keep_recent 条以外的消息,压缩成一条摘要。返回新的 messages 列表。

qq_41241612的博客 113

【数据结构-5】单链表的实现

单链表,具体来说是单向的、不带头的、不循环的链表。链表由一个一个节点组成,每个节点分为数据域和指针域,数据域存放数据,指针域存放下一节点的地址。这样,就可以根据指针域中的地址找到下一个节点,节点就串起来了构成了单链表。

a bit 217

C++ 入门笔记(十七):list 入门 —— 为什么 list 不能 sort?

第17课:用大白话讲清 list 的双向链表结构、哨兵头、push_back 四步、迭代器封装、merge 与 splice 的区别,以及 vector 排序为什么常比 list 快。

wo_jack的博客 259
上一篇: 使用C语言获取文件夹地址的方法
下一篇: 截取系统API调用
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值