删除在DLL中分配的内存会导致崩溃 [英] Deleting memory which was allocated in DLL causes a crash

查看:109
本文介绍了删除在DLL中分配的内存会导致崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

亲爱的,



我有两个模块,即 main.exe A.dll 。我在一个类中声明了一个函数,即 A.dll 中的 ClassA ,如下所示:



Dear all,

I have two modules, i.e., main.exe and A.dll. I have a function declared in a class, i.e., ClassA in the A.dll as follows:

char* ClassA::ReadFile(const char *szFilePath)
{
    int length;
    char* buffer;
    if(!IsFileExist(szFilePath)) {
        return NULL;
    }
    std::ifstream is;
    is.open (szFilePath, std::ios::binary);

    // get length of file:
    is.seekg (0, std::ios::end);
    length = is.tellg();
    is.seekg (0, std::ios::beg);

    // allocate memory:
    buffer = new char [length +1 ];             //mark line1
    memset(buffer,0,length + 1);               //mark line2

    // read data as a block:
    is.read (buffer,length);
    buffer[length] = '\0';
    is.close();
    return buffer;
}





main.exe 中,我按如下方式调用该函数:



In the main.exe, I call the function as follows:

ClassA* pA = GetClassInstanceA();

char* pszBuffTemp = pA->ReadFile();
delete[] pszBuffTemp;  // crash here!





这是问题所在。当我运行 main.exe 时,它会在删除行崩溃。但是在更改上面的mark line1和mark line2之后一切正常如下:





Here's the problem. When I run the main.exe, it comes to crash at the line "delete". But everything is ok after changing the "mark line1 and mark line2" above as follows:

buffer = new char [length + 20];             //mark line1
memset(buffer,0,length + 20 );               //mark line2





也就是说,当我为阵列分配20个字符而不是实际需要时,没有问题。我不知道原因,谢谢你的关注!





That is to say, when I alloc the array 20 chars more than the real need, there's no problem. I don't know the reason why and thank you for all your attention!

////////////////////I tried it in the other sample as follows and the crash happened also///////////

////OutApi.h//////////

#ifndef _TEXT_OUTPUT_H_
#define _TEXT_OUTPUT_H_
#ifdef _WIN32
#	ifdef   TEXTDLL_EXPROTS
#		define  TEXTDLL_API   __declspec(dllexport)  
#	else
#		 define TEXTDLL_API   __declspec(dllimport)  
#	endif
#else
#	define TEXTDLL_API
#endif
#include <string>
class Iabc
{
public:
	Iabc() {}
	virtual ~Iabc() {}
	virtual char* GetText() = 0;
};
TEXTDLL_API Iabc* GetTestIns();
#endif

////////////////  CTest.H and CTest.CPP/////////

#ifndef _asdfasdfasf_H
#define _asdfasdfasf_H

#include "./OutApi.h"

class abc:  public Iabc
{
public:
    abc(){}
    ~abc(){}

    virtual char* GetText();
};

#endif

////////CTest.CPP/////////

#include "StdAfx.h"
#include "CTest.h"

char* abc::GetText()
{
    char* temp = "test code here ,if the problem still exists!";
    int len = sizeof(temp) + 20;
    char* pResult = new char[len];
    memset(pResult, 0 ,len);
    strcpy(pResult,  temp);
    return pResult;
}

Iabc* GetTestIns()
{
    static abc a;
    return &a;
}

//////////////the implematation of the exe ///////
#include "stdafx.h"
#include "OutApi.h"
#include <string>

#include <stdio.h>

#pragma comment(lib, "TextDll.lib")

int main(int argc, char* argv[])
{
    Iabc* abcObj = GetTestIns();
    char* pFromDll = abcObj->GetText();
    delete[] pFromDll;                    ///////crash here!

    int a;
    getchar(&a);
    return 0;
}





和callstack信息如下:





and the callstack information is as follows:

NTDLL! 7c92120e()
NTDLL! 7c98e576()
NTDLL! 7c9822e8()
KERNEL32! 7c85f9a7()
_CrtIsValidHeapPointer(const void * 0x00431800) line 1606
_free_dbg(void * 0x00431800, int 1) line 1011 + 9 bytes
operator delete(void * 0x00431800) line 49 + 16 bytes
main(int 1, char * * 0x00530e80) line 16 + 15 bytes
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c817077()

推荐答案

你确定机器人的exe和dll使用相同的堆空间吗?这是极其重要的,如果他们不这样做,那肯定是你问题的根源。
Did you make sure that bot hthe exe and the dll are using the same heap space ? This is extremly important and if they don't, that's certainly the source of your problem.


[场景]

发生崩溃当应用程序(EXE)尝试删除由另一个模块(DLL)分配的内存时。



[解决方案]

在这种情况下,您有两个堆管理器相互争用;一个用于EXE,一个用于DLL。它们都是相互独立的,两者都不知道。解决这个问题的方法是使用MFC运行时库的DLL版本。这样,EXE和DLL只有一个堆管理器,因此问题可以解决。但是这个解决方案在谁可以使用DLL方面为DLL模块增加了一些限制。 (继续阅读详细信息)。



分配或释放内存的另一种方法是使用GlobalAlloc()/ GlobalLock()/ GlobalUnlock()/ GlobalFree()使用GMEM_SHARE标志的函数。这些函数是实际的Windows调用,可从操作系统获得真实内存。由于这些函数都绕过编译器的堆管理器,因此用任何语言编写的任何应用程序都可以在使用GlobalAlloc()分配的句柄上调用GlobalFree()。这是DLL为外部模块分配内存的首选方式,如果它由外部模块释放来释放内存。



如第一段所述,如果你通过纠正'运行时库'来解决这个问题,VB应用程序不能使用DLL,因为它不知道'new'和'delete'是什么......因此建议使用'Global ...'函数进行内存管理(模块之间共享)。



这个问题的另一个解决方案是,在共享DLL中提供'ReleaseMemory'接口。



选择最适合您应用的产品...
[Scenario]
Crash occurs when an application (EXE) tried to delete the memory allocated by another module (DLL).

[Solution]
In this case you have two heap managers in contention with each other; one for the EXE, and one for the DLL. Both of them are independent of each other, and both do not know anything about the other. The way around this is to use the DLL version of the MFC runtime libraries. This way there is only one heap manager for EXE and DLL, thus the issue can be solved. But this solution adds some restrictions to the DLL module in terms of who can use the DLL. (continue reading for details).

The other way of allocating or deallocating memory is to use the GlobalAlloc()/GlobalLock()/GlobalUnlock()/GlobalFree() functions using the GMEM_SHARE flag. These functions are actual Windows calls that get "real" memory from the OS. Since these functions all bypass the heap manager for the compiler, any application written in any language can call GlobalFree() on a handle that was allocated with GlobalAlloc(). This is the preferred way that DLL's allocate memory for external modules if it is up to the external module to free the memory.

As discussed in the first paragraph, if you solve this issue by correcting 'runtime library', a VB application cannot use the DLL as it does not know what 'new' and 'delete' is... So it is recommended to use 'Global...' functions for memory management (shared between modules).

Another solution to this issue is, provide 'ReleaseMemory' interface in shared DLL.

Choose the best one that suits your application...


分配数组时,您忘记考虑字符串终止零。你需要为长度+ 1的大小分配你的数组。

请记住,C ++中的数组是基于零的,这意味着当你分配一个包含10个元素的数组时,最后一个元素是在索引9而不是10。
When you allocate your array, you forgot to take in consideration the string termination zero. You need to allocate your array for a size of length+1.
Remember that arrays in C++ are zero based, which means that when you allocate an array of 10 elements, the last element is at index 9 and not 10.


这篇关于删除在DLL中分配的内存会导致崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆