Удаление памяти, которая была выделена в DLL, приводит к сбою
Дорогие все,
У меня есть два модуля, т. е., main.exe и A.dll. У меня есть функция, объявленная в классе, т. е.,
ClassA
в A.dll следующим образом: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, Я вызываю функцию следующим образом:
ClassA* pA = GetClassInstanceA(); char* pszBuffTemp = pA->ReadFile(); delete[] pszBuffTemp; // crash here!
Вот в чем проблема. Когда я запускаю main.exe, он приходит к сбою в строке "удалить". Но все в порядке после изменения "mark line1 и mark line2" выше следующим образом:
buffer = new char [length + 20]; //mark line1 memset(buffer,0,length + 20 ); //mark line2
То есть, когда я выделяю массив на 20 символов больше, чем нужно, проблем нет. Я не знаю причины этого и благодарю вас за все ваше внимание!
////////////////////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; }
а информация о стеке вызовов выглядит следующим образом:
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()
Richard MacCutchan
Пробовали ли вы пройти через этот код с помощью отладчика, чтобы точно увидеть, что происходит? Вы уверены, что указатель, который вы передаете delete
не был ли он каким-либо образом испорчен?
xunbei100
конечно, я прошел через этот код несколько раз и проверил содержимое памяти по значению указателя. и если я удалю массив в функции "readfile", то никаких проблем не возникнет.
Niklas L
Вы делаете много ненужных вызовов memset. Нет никакого смысла очищать буфер, который вы непосредственно заполняете символами, и там, где это необходимо, pBuffer[0] = 0 работает просто отлично.