首页 > 系统相关 >Memory leaks detection in a Windows Service written in C++

Memory leaks detection in a Windows Service written in C++

时间:2023-02-26 13:22:29浏览次数:60  
标签:startupinfoPtr Service service Windows Deleaker C++ leaks windows memory

Memory leaks detection in a Windows Service written in C++

On January 25, 2020 By Artem Razin In Uncategorized

Introduction

This article will demonstrate how to find memory leaks in a windows service written in C++ or plain C.

Windows service is a special kind of application, that runs in the background and follows special rules and cooperates with the Service Component Manager. A windows service is controlled by the Service Component Manager: it starts, pauses, stops and resumes windows services.

Being a long-running process, a windows service might have leaks that are hard to find. It may be memory blocks that are periodically allocated, or handles that are opened on each request. Suddenly a windows service process closes, running out of memory, or exits unexpectedly because an operation of opening a file fails.

In general, a developer may run into obstacles while profiling windows services. Let’s look at how Deleaker can help you with such issues.

Deleaker is a memory profiler for C++ that works as a standalone application, or as a plugin for all popular IDEs, including Visual Studio. In case a developer can reproduce memory leakage in development environment, using Deleaker as a plugin is very reasonable, as Deleaker cooperates with Visual Studio, and one can easily navigate to the source code of a leak. But very often a windows service leaks in production only; in such case standalone version of Deleaker is to the rescue.

Building a windows service

For this tutorial, let’s create a simple windows service. Launch Visual Studio, select ATL Project, name the project as “SampleService”. Choose Service (.exe) as Application type at last step.

Visual Studio creates several files with basic code for the windows service. By default, it is supposed that some COM objects will be added, but the sample service is not the case. To prevent the service from immediate stopping, add the following line to pch.h:

1 #define _ATL_NO_COM_SUPPORT 1

Also there is a known bug that prevents the service from starting. Let’s apply suggested changes to workaround the bug:

1 2 3 4 5 HRESULT PreMessageLoop(int nShowCmd) {     SetServiceStatus(SERVICE_RUNNING);     return __super::PreMessageLoop(nShowCmd); }

But what useful will the service do? Well, the task is simple and useful: to ping some host and log information about its availability. The service will do the task in a separate thread, so let’s run the thread in Start() method. To ping let’s use the system utility ping.exe that is launching in infinite loop:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 HRESULT Start(int nShowCmd) throw() {     _beginthreadex(nullptr, 0, &PingProc, this, 0, 0);       return __super::Start(nShowCmd); }   static unsigned __stdcall PingProc(void* param) {     auto thisPtr = (CSampleServiceModule*)param;       while (true)     {         STARTUPINFOA* startupinfoPtr = new STARTUPINFOA;         memset(startupinfoPtr, 0, sizeof(*startupinfoPtr));         startupinfoPtr->cb = sizeof(*startupinfoPtr);           PROCESS_INFORMATION pi;         const BOOL res = CreateProcessA(             nullptr,             "ping.exe google.com",             nullptr,             nullptr,             FALSE,             0,             nullptr,             nullptr,             startupinfoPtr,             &pi);           if (!res)         {             thisPtr->LogEvent(L"Failed to run ping.exe");             return 0;         }           WaitForSingleObject(pi.hProcess, INFINITE);         DWORD exitCode;         GetExitCodeProcess(pi.hProcess, &exitCode);           if (0 != exitCode)             thisPtr->LogEvent(L"Failed to ping google.com");         else             thisPtr->LogEvent(L"google.com is reachable");     }       return 1; }

At first glance, the code looks well: a process of ping.exe is started, then the code waits until the process exits, and finally some text is written to the log depending on the exit code.

Now we can build the project. Once it’s built, register the service from the command line (you need to launch cmd.exe as administrator), launching the service’s exe with switch /Service. Please notice that you should use the full path of the service exe:

“V:\Projects\Deleaker\SampleService\Debug\SampleService.exe” /Service

Find leaks of windows service in Visual Studio

To start service let’s launch using services.msc. Find SampleService there, open context menu and select Start:

Show how to start Windows Service

But suddenly one notices that the number of opened handlers and memory usage are increasing:

Task Manager shows a process memory leakage

It’s time to fix the leakage.

Start Visual Studio, ensure that Deleaker is enabled:

Display hjow to enable Deleaker in Visual Studio

A windows service is started by the Service Component Manager, that is why a developer can’t just launch the service from Visual Studio as usual application. That’s why a developer has to attach to the process of the windows service. It might happen that Visual Studio will ask to run with elevated privileges if they are required for debugging. Restart Visual Studio in such case.

Also it’s a good idea to load the project of the service to help Deleaker prepare better report with knowledge what source files are from the project.

To attach to the service process, click to Debug – Attach to…, tick “Show processes from all users” and select SampleService.exe.

Now click to Extensions – Deleaker – Deleaker Window to open Deleaker and switch to Resource Usage Graph. It shows memory and handles leakage:

Demonstrates how to check a process for leakage in Deleaker

Let’s take a base snapshot, then let process allocate more memory and open some handles. After that take the second snapshot and compare the base snapshot (use Compare with…). Comparing snapshots helps you to find those leaks that occur again and again, it’s a typical scenario of resource leakage.

Now Deleaker displays some memory leaks and some handles that have to be closed:

Shows how to use snapshots comparison to find leaks

To see where a leak is made, just double-click it, or select Show source code from context menu. Deleaker opens the source file at the line directly in the editor where the allocation is made. You don’t need to leave Visual Studio to fix leaks:

Displays how to navigate to source code of a leak

Of course, we have just forgotten close handles returned by CreateProcess, and haven’t released memory allocated for STARTUPINFO. Let’s apply the changes:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 static unsigned __stdcall PingProc(void* param) {     auto thisPtr = (CSampleServiceModule*)param;       while (true)     {         STARTUPINFOA* startupinfoPtr = new STARTUPINFOA;         memset(startupinfoPtr, 0, sizeof(*startupinfoPtr));         startupinfoPtr->cb = sizeof(*startupinfoPtr);           PROCESS_INFORMATION pi;         const BOOL res = CreateProcessA(             nullptr,             "ping.exe google.com",             nullptr,             nullptr,             FALSE,             0,             nullptr,             nullptr,             startupinfoPtr,             &pi);           delete startupinfoPtr;           if (!res)         {             thisPtr->LogEvent(L"Failed to run ping.exe");             return 0;         }           WaitForSingleObject(pi.hProcess, INFINITE);         DWORD exitCode;         GetExitCodeProcess(pi.hProcess, &exitCode);           CloseHandle(pi.hThread);         CloseHandle(pi.hProcess);           if (0 != exitCode)             thisPtr->LogEvent(L"Failed to ping google.com");         else             thisPtr->LogEvent(L"google.com is reachable");     }       return 1; }

Rebuild the project, register the service once again and start. Attach to the service process and take several snapshots. They are free of leaks, so no more leaks.

Conclusion

Deleaker is a memory profiler that helps to fix memory leakage as well as leaks of handles and other resources. Windows services profiling has always been a non trivial task. Fortunately, Deleaker can successfully attach to such processes to gather information about allocations.

Use Deleaker extension in development environment, or Deleaker Standalone in production environment. With Deleaker extension a developer can quickly fix leaks without exiting Visual Studio.

 

标签:startupinfoPtr,Service,service,Windows,Deleaker,C++,leaks,windows,memory
From: https://www.cnblogs.com/ioriwellings/p/17156528.html

相关文章

  • How to fix memory leaks in C/C++ using WinDbg
    HowtofixmemoryleaksinC/C++usingWinDbgOn May30,2021 By ArtemRazin In UncategorizedContentsIntroductionExamplesofmemoryleaksThecommon......
  • Windows 下搭建 googletest 测试框架(C/C++)
    主要分为以下几个部分环境准备源代码准备googletest与测试代码编译执行一、环境准备1.MinGW可以直接下载MinGW,x86_64-posix-sjlj下载地址也可以通过下载带编......
  • 使用ccache对C++编译加速
    使用ccache对C++编译加速我们使用cmake作为C++的编译编排系统,当修改CMakeLists.txt文件之后,就会对配置文件进行更新,再去进行make的时候,缓存就失效了,需要重新编译,当项目很......
  • C++别名的使用
    c++中的别名使用,类似引用,在别名中,“&”的意思不再是取地址,而是建立一个指针,直接指向数据。这是一个小例子:#include<iostream>usingnamespacestd;intmain(){......
  • Windows黑客编程之功能技术(下)
    描述利用CreateProcess和匿名管道,获取远程命令执行的结果使用MoveFileEx和批处理脚本,实现文件自删除远程CMD关键在于捕获命令的输出结果创建匿名管道,一端写,一端读......
  • Windows黑客编程之功能技术(中)
    描述利用WM_DEVICECHANGE消息,进行u盘插拔监控利用ReadDirectoryChangesW函数,进行文件监控利用hook原始输入设备,进行按键监控记录u盘监控DialogBoxParam:在显示对话......
  • Windows系统环境变量大全
    %ALLUSERSPROFILE%列出所有用户Profile文件位置。%APPDATA%列出应用程序数据的默认存放位置。%CD%列出当前目录。%CLIENTNAME%列出联接到终端服务会话时客户端的NE......
  • Windows黑客编程之功能技术(上)
    描述利用进程快照CreateToolhelp32Snapshot,进行进程、线程、进程模块的遍历利用FindFirstFile、FindNextFile,进行文件目录的遍历进程快照的遍历遍历进程BOOLEnumPr......
  • windows查看快捷键冲突-OpenArk
    1、下载链接OpenArk2、下载后->选择内核->系统热键->进入内核模式->即可查看到所有快捷键通过过滤器可以快速查看快捷键占用情况3、测试图......
  • 没有“Windows 沙盒”选项
    首先,Windows家庭版当前暂不支持Windows沙盒! 解决方法:http://www.studyofnet.com/698821509.html外网原文:https://www.deskmodder.de/blog/2019/04/20/windows-10-h......