300分,救命!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Rayking 2003-10-12 11:09:58
typedef deque<string> strings;
函数:
_declspec(dllexport) strings StringTokenize(const char *strSrc, char cToken)
{
DWORD dwCount(0);
StrSerial strTrunc;
strings Strs;

const char *szRef = strSrc;
const char *szWalk = szRef;

if(IS_STRING_EMPTY(szRef))
return Strs;

while(true)
{
dwCount++;
if((*szWalk)==cToken)
{
strTrunc.SetStr(szRef, dwCount-1);
if(!strTrunc.StrContent.empty())
Strs.push_back(strTrunc.StrContent);
dwCount = 0;
szRef = szWalk + 1;
}
else if(*szWalk=='\0')
{
strTrunc.SetStr(szRef, dwCount-1);
if(!strTrunc.StrContent.empty())
Strs.push_back(strTrunc.StrContent);
dwCount = 0;
break;
}
szWalk++;
}
return Strs;
}
调用:
void main(int argc, char *argv[], char *envp[])
{
strings strs = StringTokenize("dlalfdsafkdlsfkdsl", 'f');
strings::iterator iter;
cout << "dlalfdsafkdlsfkdsl" << endl;
for(iter=strs.begin(); iter!=strs.end(); iter++)
{
cout << (*iter).c_str() << endl;
}

return;
}

错误:
main函数里的strs析构时发生一个ASSERTION失败_CrtIsValidePointer(pUserData)
...全文
75 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Rayking 2003-10-13
  • 打赏
  • 举报
回复
不過你說的這個是很有價值的。
Rayking 2003-10-13
  • 打赏
  • 举报
回复
我返回的是對像不是指針。
DaNiao 2003-10-13
  • 打赏
  • 举报
回复
我想起来了,DLL里分配的空间必须在原DLL里释放
原因是这样的,每个可执行模块(一个EXE或一个DLL)都有自己独立的一套 C runtime 库的实例
也就是每个模块都有自己的堆

之所以这样我想主要是因为两个原因
1。c是静态编链的语言,要使两个模块公用同一个运行期库比较麻烦
2。dll的接口应该是语言无关的,
如果你再DLL里new了一块空间,然后再把这个空间的指针返回给一个vb的EXE程序
这个vb程序是不知道该怎么释放这块空间的,因为它不知道你是用的c语言的堆还是delphi的
(不同的语言对堆的管理有很大的不同,同样是C语言不同的厂家不同的版本也是不同的)
所以WINDOWS里动态分配的空间必须在原模块里释放

STL里的queue和string都是动态分配空间的(间接的调用了new),所以你必须回到dll里释放那个对象

我建议你把程序改成这样:
_declspec(dllexport) strings* StringTokenize(const char *strSrc, char cToken)
{
Strs = new strings;
....
}
_declspec(dllexport) void Release(strings* Strs)
{
delete Strs;
}
liao2001 2003-10-13
  • 打赏
  • 举报
回复
试试:
//_declspec(dllexport) strings StringTokenize(const char *strSrc, char cToken)
_declspec(dllexport) strings _cdecl StringTokenize(const char *strSrc, char cToken)
DaNiao 2003-10-13
  • 打赏
  • 举报
回复
sorry是我搞错了,让我再看看
DaNiao 2003-10-13
  • 打赏
  • 举报
回复
这一段是我从msdn里copy出来的

The C/C++ run-time library code performs the DLL startup sequence, eliminating the need to link with a separate module as was necessary in Windows 3.x. Included in the C/C++ run-time library code is the DLL entry-point function called _DllMainCRTStartup. The _DllMainCRTStartup function does several things, including calling _CRT_INIT, which initializes the C/C++ run-time library and invokes C++ constructors on static, non-local variables. Without this function, the run-time library would be left in an uninitialized state. _CRT_INIT is available for both a statically-linked CRT, or linking to the CRT DLL msvcrt.dll, from a user DLL.

While it is possible to specify another entry-point function using the /ENTRY: linker option, it is not recommended because your entry-point function would have to duplicate everything that _DllMainCRTStartup does. When building DLLs in Visual C++, _DllMainCRTStartup is linked in automatically and you do not need to specify an entry-point function using the /ENTRY: linker option.

In addition to initializing the C run-time library, _DllMainCRTStartup calls a function called DllMain. Depending on the kind of DLL you are building, Visual C++ provides DllMain for you and it gets linked in so that _DllMainCRTStartup always has something to call. In this way, if you do not need to initialize your DLL, there's nothing special you have to do when building your DLL. If you need to initialize your DLL, where you add your code depends on the kind of DLL you are writing. See Initializing a DLL for more information.

The C/C++ run-time library code calls constructors and destructors on static, non-local variables. For example, in the following DLL source code, Equus and Sugar are two static, non-local objects of class CHorse, defined in HORSES.H. There is no function in source code that contains calls to a constructor function for CHorse or to the destructor function because these objects are defined outside of any function. Therefore, calls to these constructors and destructors must be performed by the run-time code. (The run-time library code for applications also performs this function.)

#include "horses.h"

CHorse Equus( ARABIAN, MALE );
CHorse Sugar( THOROUGHBRED, FEMALE );

BOOL WINAPI DllMain (HANDLE hInst,
ULONG ul_reason_for_call,
LPVOID lpReserved)
...
Each time a new process attempts to use the DLL, the operating system creates a separate copy of the DLL's data: this is called "process attach." The run-time library code for the DLL calls the constructors for all of the global objects, if any, and then calls the DllMain function with process attach selected. The opposite situation is process detach: the run-time library code calls DllMain with process detach selected and then calls a list of termination functions, including atexit functions, destructors for the global objects, and destructors for the static objects. Note that the order of events in process attach is the reverse of that in process detach.

The run-time library code is also called during thread attach and thread detach, but the run-time code does no initialization or termination on its own.
DaNiao 2003-10-13
  • 打赏
  • 举报
回复
你应该在DllMain里初始化C runtime library
Rayking 2003-10-13
  • 打赏
  • 举报
回复
StrSerial是對string的封裝,可以序列化。SetStr(char *pszStr, int count)方法是將字符串的前count個字符賦給StrSerial對像,僅此而已。
我已經知道怎么解決了,這是因為StringTokenize函數存在于一個DLL中,可能返回的strings對像的Allocator并沒有復制獨立于原對像的空間,所以這個反回的對像在析構時操作到非法的內存。我將這個函數直接放在要調用的程序文件里一起編繹就可以了。

我對stl實在懂得少,請多指點。這樣看是不是不能用STL在DLL中傳遞數據呢?
Rayking 2003-10-12
  • 打赏
  • 举报
回复
这个函数是将一个string按里面含的某个字符分割,将结果存入strings,strings是一个deque.
也曾偿试用如下的方式不反回一个类而是传入一个指针:
extern "C" _declspec(dllexport) void StringTokenize(string strSrc, char cToken, strings *pStrs)
{
DWORD dwCount(0);
StrSerial strTrunc;

const char *szRef = strSrc.c_str();
const char *szWalk = szRef;

if(IS_STRING_EMPTY(szRef))
return;

while(true)
{
dwCount++;
if((*szWalk)==cToken)
{
strTrunc.SetStr(szRef, dwCount-1);
pStrs->push_back(strTrunc.StrContent);
dwCount = 0;
szRef = szWalk + 1;
}
else if(*szWalk=='\0')
{
strTrunc.SetStr(szRef, dwCount-1);
pStrs->push_back(strTrunc.StrContent);
dwCount = 0;
break;
}
szWalk++;
}
}
sevecol 2003-10-12
  • 打赏
  • 举报
回复
你把你的StrSerial的代码也贴出来吧,这样一来比较好看

24,855

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧