急: 请教 C++ COM 问题

h2plus0 2005-12-08 01:26:43
请教高手, cb 调用 VB 写的一个COM dll, 在IDE环境下运行CPU view
就频繁停止在 ntdll.DbgBreakPoint ret 指令上?如果直接运行程序则出现
"Access Violation at 7C95426D in module ntdll.dll, read of address 00000017" 错误,
请问这是什么原因找成的 ?
谢谢!
...全文
215 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
h2plus0 2005-12-12
  • 打赏
  • 举报
回复

up 一下, 这是我在borland newsgroup 里问的结果, 但为什么OleFunction() 要释放
传入的Ole String 还是不清楚



> wchar_t* path3 = L"D:\\temp\\12345\\1.xml";
<snip>
> Variant t = xml.OleFunction("load", path3 );

That code fails because OleFunction() will internally take ownership of the
memory that the whar_t* pointer is pointing to. When OleFunction() returns,
it tries to free the owned memory. But it can't because the memory being
pointed to is in the executable's static read-only memory and cannot be
freed programmably at all. It is freed only when the executable is
terminated.

> however, if I use "path2.c_bstr()" instead of "path3" on
> call OleFunction load(), then run is normal and no stop

The call to OleFunction() will run without problem, but the WideString will
crash later on when it goes out of scope. If you pass a BSTR to
OleFunction(), it will take ownership of the BSTR and then free it when
OleFunction() returns. So, if you use the c_bstr() method of WideString,
OleFunction() will free the BSTR that the WideString contains, leaving the
WideString pointing to a non-invalid BSTR, which the WideString's destructor
then tries to free again. It would be better to pass the WideString itself
instead of the BSTR that it contains, as OleFunction() will make a copy of
the BSTR and then take ownership of that copy, and WideString will maintain
ownership of the original BSTR.

Variant xml = Variant::CreateObject("Microsoft.XMLDOM");
xml.OlePropertySet("async", VARIANT_FALSE);
WideString path = "D:\\temp\\12345\\1.xml";
Variant t = xml.OleFunction("load", path);
if( t )
ShowMessage("Load ok");
else
ShowMessage("Load False");

> However from COM specification, not it should use wchar_t
> (OLECHAR) instread of char ? why it can success ??

Using a char* is fine because OleFunction() will internally convert the
value to a BSTR, which it then takes ownership of.


Gambit
yesry 2005-12-12
  • 打赏
  • 举报
回复
为什么就不是很清楚了,知道怎么就行了。
h2plus0 2005-12-09
  • 打赏
  • 举报
回复
说明一下,xml文件随便搞一个就行, 最好放在一个中文目录中,
传path1 时, 这样
Variant t = xml.OleFunction("Load", path1.c_str() );
path2 都可以
Variant t = xml.OleFunction("Load", path2 );
Variant t = xml.OleFunction("Load", path2.c_bstr() );

但为什么 path3 不行啊?
Variant t = xml.OleFunction("Load", path3 );

h2plus0 2005-12-09
  • 打赏
  • 举报
回复
终于知道大致什么原因导致出错了, 下面代码可以重现问题, 但如果 Load()传 path1/path2
就没问题。 奇怪了, COM 不是应该传 wide char 吗?难道 OleFunction() 会自动转换吗?

Variant xml = Variant::CreateObject("Microsoft.XMLDOM");
xml.OlePropertySet("Async", VARIANT_FALSE);
AnsiString path1 = "E:\\work\\archive\\共享文件例子\\exchange\\archive\\7243\\7243.xml";
WideString path2 = "E:\\work\\archive\\共享文件例子\\exchange\\archive\\7243\\7243.xml";
wchar_t* path3 = L"E:\\work\\archive\\共享文件例子\\exchange\\archive\\7243\\7243.xml";

// ensure path2==path3
if (path2.Length()!=wcslen(path3) ) {
ShowMessage("!=");
return;
}
for(unsigned int i=0;i<path2.Length();i++) {
if (path2[i+1]!=path3[i]) {
ShowMessage("!= 2222");
return;
}
}

Variant t = xml.OleFunction("Load", path3);
if (t) {
ShowMessage("load ok");
}
else {
ShowMessage("Load False");
}
cbdxl 2005-12-09
  • 打赏
  • 举报
回复
学习
CACACACACA 2005-12-09
  • 打赏
  • 举报
回复
没装2006呢.
zzscll 2005-12-09
  • 打赏
  • 举报
回复
我的2006,还没下载完呢
只能接分了
h2plus0 2005-12-09
  • 打赏
  • 举报
回复

谁能在 2006 上帮我试一下啊。。。

不过这好像也不是编译器的问题, 因为 path2.c_bstr() 都可以, 但path3 为什么就不行啊?

任何提示都将非常感激!

以前认为好像COM 并不复杂, 但现在搞起来,差不多快疯掉 。。。
leonatcs 2005-12-08
  • 打赏
  • 举报
回复
呵呵,这么看恐怕没人能帮上你了,接分了。

对了,用CodeGuard试试,如果问题出在你的程序,那它很可能帮你找到。
h2plus0 2005-12-08
  • 打赏
  • 举报
回复
由于VB的DLL 是其他公司开发的, 我在这只能贴出我的代码,但问题是大家都不能重现这个问题。(需要安装一个档案系统 300M) ...

而且代码很长, 我现在还不能确定到底是那句出错, 因为它每次都跑到
ntdll.DbgBreakPoint , 如果不停的F9, 有时会出现 out of memory

我有点怀疑 Variant VARIANT 之间有一点问题, 应为那个函数需要
传一个 BStr的 数组, 接口定义是
virtual HRESULT STDMETHODCALLTYPE set_GetFile(VARIANT Param1/*[in]*/) = 0; // [1745027074]

但我传了一个 Variant , 是用 VarArrayCreate 创建的, 我正在看Windows API 怎么
操作VARIANT, 如果有结果再和大家讨论,谢谢!
yesry 2005-12-08
  • 打赏
  • 举报
回复
什么方式调用的啊?最好有代码。

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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