simple isapi extension : memory leak detected

From: Marty Sheffield (someone_at_online.com)
Date: 03/25/05


Date: Fri, 25 Mar 2005 12:01:06 -0800

I started by trying to figure out where a memory leak in my isapi
extension was coming from, so I built a super simple MFC isapi with the
wizard (using VS .net 2002). It only has 3 parse commands; default,
emptyTest, and variableTest. Both default & emptyTest take no
parameters, the latter takes one. Whenever I call the methods that do
not take variables, I dont see a leak. When i call the variable test
(/testIsapi.dll?variableTest&var=test), CRT detects leaks when the dll is
unloaded (there's always 4 reported leaks). I'm wondering what gives,
and what I can do to correct this, I've been googling all day.

<the error>
[2248] Detected memory leaks!
[2248] Dumping objects ->
[2248] {55}
[2248] normal block at 0x00A64090, 8 bytes long.
[2248] Data: < > CD CD CD CD CD CD CD CD
[2248] {54}
[2248] normal block at 0x00A64058, 8 bytes long.
[2248] Data: <(@ > 28 40 A6 00 00 00 00 00
[2248] {53}
[2248] normal block at 0x00A64028, 4 bytes long.
[2248] Data: <var > 76 61 72 00
[2248] {52}
[2248] normal block at 0x00A62958, 16 bytes long.
[2248] Data: < X@ @ > 01 00 00 00 01 00 00 00 58 40 A6 00 90
40 A6 00

<testIsapi.cpp>
// testIsapi.cpp - Implementation file for ISAPI
// testIsapi Extension

#include "stdafx.h"
#include "testIsapi.h"

// The one and only CWinApp object
// NOTE: You may remove this object if you alter your project to no
// longer use MFC in a DLL.

CWinApp theApp;

// command-parsing map

BEGIN_PARSE_MAP(CtestIsapiExtension, CHttpServer)
        // TODO: insert your ON_PARSE_COMMAND() and
        // ON_PARSE_COMMAND_PARAMS() here to hook up your commands.
        // For example:

        ON_PARSE_COMMAND(Default, CtestIsapiExtension, ITS_EMPTY)

        ON_PARSE_COMMAND(emptyTest, CtestIsapiExtension, ITS_EMPTY)

  ON_PARSE_COMMAND(variableTest, CtestIsapiExtension, ITS_PSTR)
  ON_PARSE_COMMAND_PARAMS("var=~")

        DEFAULT_PARSE_COMMAND(Default, CtestIsapiExtension)
END_PARSE_MAP(CtestIsapiExtension)

// The one and only CtestIsapiExtension object

CtestIsapiExtension theExtension;

// CtestIsapiExtension implementation

CtestIsapiExtension::CtestIsapiExtension()
{
  _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
}

CtestIsapiExtension::~CtestIsapiExtension()
{
  _CrtDumpMemoryLeaks();

}

BOOL CtestIsapiExtension::GetExtensionVersion(HSE_VERSION_INFO* pVer)
{
        // Call default implementation for initialization
        CHttpServer::GetExtensionVersion(pVer);

        // Load description string
        TCHAR sz[HSE_MAX_EXT_DLL_NAME_LEN+1];
        ISAPIVERIFY(::LoadString(AfxGetResourceHandle(),
                        IDS_SERVER, sz, HSE_MAX_EXT_DLL_NAME_LEN));
        _tcscpy(pVer->lpszExtensionDesc, sz);
        return TRUE;
}

BOOL CtestIsapiExtension::TerminateExtension(DWORD dwFlags)
{
        // extension is being terminated
        //TODO: Clean up any per-instance resources
        return TRUE;
}

// CtestIsapiExtension command handlers

void CtestIsapiExtension::Default(CHttpServerContext* pCtxt)
{
        StartContent(pCtxt);
        WriteTitle(pCtxt);

        *pCtxt << _T("This is the default message");

        EndContent(pCtxt);
}

// CtestIsapiExtension command handlers

void CtestIsapiExtension::emptyTest(CHttpServerContext* pCtxt)
{
        StartContent(pCtxt);
        WriteTitle(pCtxt);

        *pCtxt << _T("This is the emptyTest page<br>\r\n");

        EndContent(pCtxt);
}

// CtestIsapiExtension command handlers

void CtestIsapiExtension::variableTest(CHttpServerContext* pCtxt, LPTSTR
pszVar)
{
        StartContent(pCtxt);
        WriteTitle(pCtxt);

        *pCtxt << _T("This is the variableTest page<br>\r\n");
        *pCtxt << _T(pszVar);
  *pCtxt << _T("<br>\r\n");

        EndContent(pCtxt);
}

// If your extension will not use MFC, you'll need this code to make
// sure the extension objects can find the resource handle for the
// module. If you convert your extension to not be dependent on MFC,
// remove the comments around the following AfxGetResourceHandle()
// and DllMain() functions, as well as the g_hInstance global.

/****

static HINSTANCE g_hInstance;

HINSTANCE AFXISAPI AfxGetResourceHandle()
{
        return g_hInstance;
}

BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason,
                                        LPVOID lpReserved)
{
        if (ulReason == DLL_PROCESS_ATTACH)
        {
                g_hInstance = hInst;
        }

        return TRUE;
}

****/

<testIsapi.h>
#pragma once

// testIsapi.h - Header file for your Internet Information Server
// testIsapi Extension

#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif

#include "resource.h"

class CtestIsapiExtension : public CHttpServer
{
public:
        CtestIsapiExtension();
        ~CtestIsapiExtension();

        // Overrides
public:
        virtual BOOL GetExtensionVersion(HSE_VERSION_INFO* pVer);
        virtual BOOL TerminateExtension(DWORD dwFlags);

        // TODO: Add handlers for your commands here.
        // For example:

        void Default(CHttpServerContext* pCtxt);
  void emptyTest(CHttpServerContext* pCtxt);
  void variableTest(CHttpServerContext* pCtxt, LPTSTR pszVar);

        DECLARE_PARSE_MAP()
};



Relevant Pages

  • Re: C Program [ Turbo-C ] , to extract only-Printable-characters from a file ( any type
    ... So C99 formalises the idea that aform of mainis valid on an ... > implementation documents it as an extension. ... OK I see an argument that the bit from C99 above legitimises ... > void mainand in my book that makes void mainan invalid ...
    (comp.lang.c)
  • Re: Question about void pointers
    ... got to switch to char * so that it can be incremented properly. ... You have two options, do it portably, or do it with an extension, with ... perhaps the OP doesn't need portability (or at least not this ... void * seems more natural for this kind ...
    (comp.lang.c)
  • Re: Alternate declarations for main
    ... using 'void main'. ... The confusion stems from the fact that the standard actually mentions ... Because the reasons are ... who uses an extension is already aware that his code is non-portable. ...
    (comp.std.c)
  • Re: Question about void pointers
    ... You have two options, do it portably, or do it with an extension, with ... kind of portability). ... void * seems more natural for this kind ... This "investigate doodle" demonstrated this kind of task. ...
    (comp.lang.c)
  • Re: How to analyze kmemleak message?
    ... void foo ... Kmemleak tries to avoid the reporting of transient leaks by only ... I don't want kmemleak to report such memory as memory leaks. ...
    (Linux-Kernel)

Quantcast