18 个解决方案
#1
com初始化是线程相关的,每个线程都独立的初始化和释放 .
试一试:CoinitilizeEx和oleinitialize ,这三个方法还是有些区别.
试一试:CoinitilizeEx和oleinitialize ,这三个方法还是有些区别.
#2
刚到公司就按照你的方法试了一下,错误照旧,其实CoinitilizeEx这个函数我早就试过了,就是解决不了啊,十分郁闷。
#3
这个是个套间问题,LZ你看看你的代码结构是不是这样,我简单描述
主线程
{
coinitiliza(NULL)
子线程
{
coinitiliza(NULL)
uncoinitiliza()
}
convertBTRToString
uncoinitiliza()
}
如果是如上面,那就有可能是,主线程运行时把子线程起来了,但子线程结束时调用了uncoinitiliza()所以com库就已经被释放了。所以再调用和一些COM相关的函数就不行了。LZ可以这样式,把子线程对COM库的注册和返注册注释掉。
#4
我确实是在主线程启东市,立刻启动了子线程,等待主线程的消息,子线程开始工作,现在顺序是这样的,主线程先初始化com,启动子线程,子线程com口初始化,等待消息,到这里都没有问题,子线程解析XML也没有问题(如果注释掉注册,就会CreateInstance失败(尚未调用coinitiliza)),但是因为IXMLDOMNodePtr::text是_bstr_t类型的,而我的相关结构里的属性是char *的,我跟踪了一下,运行到_bstr_t::m_Data::getString()的时候,需要调用_com::convertBTRToString()函数,一旦到这里,就会包内存错误,我都没辙了
#5
建议LZ:1,调用GetLastError看返回的错误码;
2,LZ能不能把convertBTRToString句左右的代码帖出来,我们也好帮你分析一下是否是API的用法出现了问题?
#6
多谢SiGoYi,错误就是在这个函数里发生的,奇怪的是主线程有一个函数和这个差不多,却没有出问题
bool Download::XmlToLinkTable(const char *fileConent)
{
//::CoInitialize(NULL); //这句话导致了我的内存问题
MSXML::IXMLDOMDocumentPtr pDoc;
MSXML::IXMLDOMElementPtr pEl;
HRESULT hr = pDoc.CreateInstance(MSXML::CLSID_DOMDocument);
if (FAILED(hr))
{
_com_error er(hr);
return false;
}
variant_t vResult;
vResult = pDoc->loadXML(fileConent);
//_bstr_t sPath("new.xml");
//vResult = pDoc->load(sPath);
if ((BOOL)vResult == FALSE){
WriteLog("载入XML时发生了错误, 请检查XML文档路径", logPath);
return false;
}
if (pDoc->parseError->errorCode != 0) {
WriteLog("XML解析时发生了错误, 请检查XML文档", logPath);
return false;
}
WriteLog("远程XML配置文件解析成功!", logPath);
pEl = pDoc->documentElement;
for (MSXML::IXMLDOMNodePtr pChild = pEl->firstChild; NULL != pChild; pChild = pChild->nextSibling) {
DATAFILENODE *node = new DATAFILENODE;
strcpy_s(node->url, MAX_PATH, pChild->text);
/*
上面这句话调用strcpy_s,最后一个参数是char*的,我把_bstr_t 的字符串给进去后,会调用隐式的转换,
就是_bstr_t::m_Data::getString()函数,这个是微软的函数,他会调用_com::convertBTRToString()函数,
跟踪到这里再下一步就会报内存错误了。
*/
splitPath(node->url, node->name, node->fullPath);
node->next = NULL;
InsertNode(node);
}
WriteLog("到达任务时间,远程配置文件加载成功,开始下载...", logPath);
return true;
//采用tinyxml运行库解析xml
//date:2010-3-2
}
bool Download::XmlToLinkTable(const char *fileConent)
{
//::CoInitialize(NULL); //这句话导致了我的内存问题
MSXML::IXMLDOMDocumentPtr pDoc;
MSXML::IXMLDOMElementPtr pEl;
HRESULT hr = pDoc.CreateInstance(MSXML::CLSID_DOMDocument);
if (FAILED(hr))
{
_com_error er(hr);
return false;
}
variant_t vResult;
vResult = pDoc->loadXML(fileConent);
//_bstr_t sPath("new.xml");
//vResult = pDoc->load(sPath);
if ((BOOL)vResult == FALSE){
WriteLog("载入XML时发生了错误, 请检查XML文档路径", logPath);
return false;
}
if (pDoc->parseError->errorCode != 0) {
WriteLog("XML解析时发生了错误, 请检查XML文档", logPath);
return false;
}
WriteLog("远程XML配置文件解析成功!", logPath);
pEl = pDoc->documentElement;
for (MSXML::IXMLDOMNodePtr pChild = pEl->firstChild; NULL != pChild; pChild = pChild->nextSibling) {
DATAFILENODE *node = new DATAFILENODE;
strcpy_s(node->url, MAX_PATH, pChild->text);
/*
上面这句话调用strcpy_s,最后一个参数是char*的,我把_bstr_t 的字符串给进去后,会调用隐式的转换,
就是_bstr_t::m_Data::getString()函数,这个是微软的函数,他会调用_com::convertBTRToString()函数,
跟踪到这里再下一步就会报内存错误了。
*/
splitPath(node->url, node->name, node->fullPath);
node->next = NULL;
InsertNode(node);
}
WriteLog("到达任务时间,远程配置文件加载成功,开始下载...", logPath);
return true;
//采用tinyxml运行库解析xml
//date:2010-3-2
}
#7
请问LZ,bool Download::XmlToLinkTable(const char *fileConent)这个函数应该是你子线程调用的吧!如果是你把::CoInitialize(NULL);加在线程函数的开头式式,明白什么意思吧!就是在你的创建子线程时那个子线程入口函数,在那个函数头加CoInitialize(NULL);在退出函数之前再调用UnConInitialize();其余的在子线程函数里调用的都去掉。这样应该差不多。如果好用了你再回复一下,我再帮你看看代码。
#8
学习
mark
mark
#9
楼主我好像知道你的问题所在了,DATAFILENODE *node = new DATAFILENODE;看看DATAFILENODE结构体应该是你自己定义的吧,再看DATAFILENODE中的url成员,应该是个char*吧!你是不是没有分配内存啊!是不是应该先new一下啊!因为下面的API strcpy_s要往DATAFILENODE的成员url中拷贝,如果你不先分配内存是不行的。
#10
谢谢SiGoYi,但是我的结构属性有关字符串的都是这么定义的
typedef struct pDATAFILENODE {
char url[260];
char otherProperty[size];
}DATAFILENODE;
所以应该不是分配内存的问题,还有,这个函数的开头原来确实是调用::CoInitialize(NULL)的,但是后来已经改成在函数入口点调用了,问题并没有解决啊。
入口看书如下:
unsigned __stdcall ThreadMain(LPVOID pParam)
{
::CoInitialize(NULL);
//监视者线程
MSG msg;//该线程接收到的消息
Download d; //任务对象,当线程接收到不同的消息时有不同的工作要完成
d.GetConfig(&theApp.conf);
d.GetLogPath(theApp.logPath);
d.GetDlThreadId(nDlThreadId);
d.GetRsThreadId(nRsThreadId);
while(true){
if(::GetMessage(&msg, NULL, NULL, NULL)) {
switch(msg.message){
case WM_TIMEISUP:
{
d.StartDownload();
break;
}
case WM_DOWNLOADISCOMPLETE:
{
/*2010-2-24 下载完成的消息发送到这里,指示Downlaod d对象遍历链表*/
d.GetRemoteFile(NULL, msg.lParam);
break;
}
default:
break;
}
}
};
return 0;
}
typedef struct pDATAFILENODE {
char url[260];
char otherProperty[size];
}DATAFILENODE;
所以应该不是分配内存的问题,还有,这个函数的开头原来确实是调用::CoInitialize(NULL)的,但是后来已经改成在函数入口点调用了,问题并没有解决啊。
入口看书如下:
unsigned __stdcall ThreadMain(LPVOID pParam)
{
::CoInitialize(NULL);
//监视者线程
MSG msg;//该线程接收到的消息
Download d; //任务对象,当线程接收到不同的消息时有不同的工作要完成
d.GetConfig(&theApp.conf);
d.GetLogPath(theApp.logPath);
d.GetDlThreadId(nDlThreadId);
d.GetRsThreadId(nRsThreadId);
while(true){
if(::GetMessage(&msg, NULL, NULL, NULL)) {
switch(msg.message){
case WM_TIMEISUP:
{
d.StartDownload();
break;
}
case WM_DOWNLOADISCOMPLETE:
{
/*2010-2-24 下载完成的消息发送到这里,指示Downlaod d对象遍历链表*/
d.GetRemoteFile(NULL, msg.lParam);
break;
}
default:
break;
}
}
};
return 0;
}
#11
这个错误应该和CoInitialize没什么关系,CoInitialize只是初始化线程Com环境,是个API函数.你仔细跟踪一下convertBTRToString函数,看看为什么出错吧,如果实在找不出什么错误,就用WideCharToMultiByte函数算了
#12
我在我本地写了这样的代码
//CoInitialize(NULL);
typedef struct pDATAFILENODE {
char url[260];
char otherProperty[10];
}DATAFILENODE;
DATAFILENODE* p = new DATAFILENODE;
_bstr_t a = SysAllocString(_T("abc"));
strcpy_s(p->url, 5, a);
感觉CoInitialize调用或不调用下面的strcpy_s都能成功啊!真想不出来为什么了!
#13
LZ也可以把url这个成员的类型改成_bstr_t之后用_bstr_t的copy()函数来实现拷贝。
#14
谢谢skybblue,我试过改用WideCharToMultiByte函数,但是依然有内存问题,google了一些帖子,好像说convertBTRToString内部也调用WideCharToMultiByte函数的。
#15
说的是啊,在主线程做同样的事情,没有任何问题,而且我还测试过,在CoInitialize函数的前面和后面都做wchar_t到char的转换,结果在调用之前成功了,而之后那个,失败了
#16
关注中~~~~~~~~~~~~~~求高手指导啊!
#17
线程套间的问题
可参考http://www.codeproject.com/KB/COM/CCOMThread2.aspx
可参考http://www.codeproject.com/KB/COM/CCOMThread2.aspx
#18
问题找到了,是我三个同时启动的线程中的一个线程中,一个char 字符串 在memset过程中size设定超过了char字符串本尊的长度,现在没问题了,还是谢谢大家
#1
com初始化是线程相关的,每个线程都独立的初始化和释放 .
试一试:CoinitilizeEx和oleinitialize ,这三个方法还是有些区别.
试一试:CoinitilizeEx和oleinitialize ,这三个方法还是有些区别.
#2
刚到公司就按照你的方法试了一下,错误照旧,其实CoinitilizeEx这个函数我早就试过了,就是解决不了啊,十分郁闷。
#3
这个是个套间问题,LZ你看看你的代码结构是不是这样,我简单描述
主线程
{
coinitiliza(NULL)
子线程
{
coinitiliza(NULL)
uncoinitiliza()
}
convertBTRToString
uncoinitiliza()
}
如果是如上面,那就有可能是,主线程运行时把子线程起来了,但子线程结束时调用了uncoinitiliza()所以com库就已经被释放了。所以再调用和一些COM相关的函数就不行了。LZ可以这样式,把子线程对COM库的注册和返注册注释掉。
#4
我确实是在主线程启东市,立刻启动了子线程,等待主线程的消息,子线程开始工作,现在顺序是这样的,主线程先初始化com,启动子线程,子线程com口初始化,等待消息,到这里都没有问题,子线程解析XML也没有问题(如果注释掉注册,就会CreateInstance失败(尚未调用coinitiliza)),但是因为IXMLDOMNodePtr::text是_bstr_t类型的,而我的相关结构里的属性是char *的,我跟踪了一下,运行到_bstr_t::m_Data::getString()的时候,需要调用_com::convertBTRToString()函数,一旦到这里,就会包内存错误,我都没辙了
#5
建议LZ:1,调用GetLastError看返回的错误码;
2,LZ能不能把convertBTRToString句左右的代码帖出来,我们也好帮你分析一下是否是API的用法出现了问题?
#6
多谢SiGoYi,错误就是在这个函数里发生的,奇怪的是主线程有一个函数和这个差不多,却没有出问题
bool Download::XmlToLinkTable(const char *fileConent)
{
//::CoInitialize(NULL); //这句话导致了我的内存问题
MSXML::IXMLDOMDocumentPtr pDoc;
MSXML::IXMLDOMElementPtr pEl;
HRESULT hr = pDoc.CreateInstance(MSXML::CLSID_DOMDocument);
if (FAILED(hr))
{
_com_error er(hr);
return false;
}
variant_t vResult;
vResult = pDoc->loadXML(fileConent);
//_bstr_t sPath("new.xml");
//vResult = pDoc->load(sPath);
if ((BOOL)vResult == FALSE){
WriteLog("载入XML时发生了错误, 请检查XML文档路径", logPath);
return false;
}
if (pDoc->parseError->errorCode != 0) {
WriteLog("XML解析时发生了错误, 请检查XML文档", logPath);
return false;
}
WriteLog("远程XML配置文件解析成功!", logPath);
pEl = pDoc->documentElement;
for (MSXML::IXMLDOMNodePtr pChild = pEl->firstChild; NULL != pChild; pChild = pChild->nextSibling) {
DATAFILENODE *node = new DATAFILENODE;
strcpy_s(node->url, MAX_PATH, pChild->text);
/*
上面这句话调用strcpy_s,最后一个参数是char*的,我把_bstr_t 的字符串给进去后,会调用隐式的转换,
就是_bstr_t::m_Data::getString()函数,这个是微软的函数,他会调用_com::convertBTRToString()函数,
跟踪到这里再下一步就会报内存错误了。
*/
splitPath(node->url, node->name, node->fullPath);
node->next = NULL;
InsertNode(node);
}
WriteLog("到达任务时间,远程配置文件加载成功,开始下载...", logPath);
return true;
//采用tinyxml运行库解析xml
//date:2010-3-2
}
bool Download::XmlToLinkTable(const char *fileConent)
{
//::CoInitialize(NULL); //这句话导致了我的内存问题
MSXML::IXMLDOMDocumentPtr pDoc;
MSXML::IXMLDOMElementPtr pEl;
HRESULT hr = pDoc.CreateInstance(MSXML::CLSID_DOMDocument);
if (FAILED(hr))
{
_com_error er(hr);
return false;
}
variant_t vResult;
vResult = pDoc->loadXML(fileConent);
//_bstr_t sPath("new.xml");
//vResult = pDoc->load(sPath);
if ((BOOL)vResult == FALSE){
WriteLog("载入XML时发生了错误, 请检查XML文档路径", logPath);
return false;
}
if (pDoc->parseError->errorCode != 0) {
WriteLog("XML解析时发生了错误, 请检查XML文档", logPath);
return false;
}
WriteLog("远程XML配置文件解析成功!", logPath);
pEl = pDoc->documentElement;
for (MSXML::IXMLDOMNodePtr pChild = pEl->firstChild; NULL != pChild; pChild = pChild->nextSibling) {
DATAFILENODE *node = new DATAFILENODE;
strcpy_s(node->url, MAX_PATH, pChild->text);
/*
上面这句话调用strcpy_s,最后一个参数是char*的,我把_bstr_t 的字符串给进去后,会调用隐式的转换,
就是_bstr_t::m_Data::getString()函数,这个是微软的函数,他会调用_com::convertBTRToString()函数,
跟踪到这里再下一步就会报内存错误了。
*/
splitPath(node->url, node->name, node->fullPath);
node->next = NULL;
InsertNode(node);
}
WriteLog("到达任务时间,远程配置文件加载成功,开始下载...", logPath);
return true;
//采用tinyxml运行库解析xml
//date:2010-3-2
}
#7
请问LZ,bool Download::XmlToLinkTable(const char *fileConent)这个函数应该是你子线程调用的吧!如果是你把::CoInitialize(NULL);加在线程函数的开头式式,明白什么意思吧!就是在你的创建子线程时那个子线程入口函数,在那个函数头加CoInitialize(NULL);在退出函数之前再调用UnConInitialize();其余的在子线程函数里调用的都去掉。这样应该差不多。如果好用了你再回复一下,我再帮你看看代码。
#8
学习
mark
mark
#9
楼主我好像知道你的问题所在了,DATAFILENODE *node = new DATAFILENODE;看看DATAFILENODE结构体应该是你自己定义的吧,再看DATAFILENODE中的url成员,应该是个char*吧!你是不是没有分配内存啊!是不是应该先new一下啊!因为下面的API strcpy_s要往DATAFILENODE的成员url中拷贝,如果你不先分配内存是不行的。
#10
谢谢SiGoYi,但是我的结构属性有关字符串的都是这么定义的
typedef struct pDATAFILENODE {
char url[260];
char otherProperty[size];
}DATAFILENODE;
所以应该不是分配内存的问题,还有,这个函数的开头原来确实是调用::CoInitialize(NULL)的,但是后来已经改成在函数入口点调用了,问题并没有解决啊。
入口看书如下:
unsigned __stdcall ThreadMain(LPVOID pParam)
{
::CoInitialize(NULL);
//监视者线程
MSG msg;//该线程接收到的消息
Download d; //任务对象,当线程接收到不同的消息时有不同的工作要完成
d.GetConfig(&theApp.conf);
d.GetLogPath(theApp.logPath);
d.GetDlThreadId(nDlThreadId);
d.GetRsThreadId(nRsThreadId);
while(true){
if(::GetMessage(&msg, NULL, NULL, NULL)) {
switch(msg.message){
case WM_TIMEISUP:
{
d.StartDownload();
break;
}
case WM_DOWNLOADISCOMPLETE:
{
/*2010-2-24 下载完成的消息发送到这里,指示Downlaod d对象遍历链表*/
d.GetRemoteFile(NULL, msg.lParam);
break;
}
default:
break;
}
}
};
return 0;
}
typedef struct pDATAFILENODE {
char url[260];
char otherProperty[size];
}DATAFILENODE;
所以应该不是分配内存的问题,还有,这个函数的开头原来确实是调用::CoInitialize(NULL)的,但是后来已经改成在函数入口点调用了,问题并没有解决啊。
入口看书如下:
unsigned __stdcall ThreadMain(LPVOID pParam)
{
::CoInitialize(NULL);
//监视者线程
MSG msg;//该线程接收到的消息
Download d; //任务对象,当线程接收到不同的消息时有不同的工作要完成
d.GetConfig(&theApp.conf);
d.GetLogPath(theApp.logPath);
d.GetDlThreadId(nDlThreadId);
d.GetRsThreadId(nRsThreadId);
while(true){
if(::GetMessage(&msg, NULL, NULL, NULL)) {
switch(msg.message){
case WM_TIMEISUP:
{
d.StartDownload();
break;
}
case WM_DOWNLOADISCOMPLETE:
{
/*2010-2-24 下载完成的消息发送到这里,指示Downlaod d对象遍历链表*/
d.GetRemoteFile(NULL, msg.lParam);
break;
}
default:
break;
}
}
};
return 0;
}
#11
这个错误应该和CoInitialize没什么关系,CoInitialize只是初始化线程Com环境,是个API函数.你仔细跟踪一下convertBTRToString函数,看看为什么出错吧,如果实在找不出什么错误,就用WideCharToMultiByte函数算了
#12
我在我本地写了这样的代码
//CoInitialize(NULL);
typedef struct pDATAFILENODE {
char url[260];
char otherProperty[10];
}DATAFILENODE;
DATAFILENODE* p = new DATAFILENODE;
_bstr_t a = SysAllocString(_T("abc"));
strcpy_s(p->url, 5, a);
感觉CoInitialize调用或不调用下面的strcpy_s都能成功啊!真想不出来为什么了!
#13
LZ也可以把url这个成员的类型改成_bstr_t之后用_bstr_t的copy()函数来实现拷贝。
#14
谢谢skybblue,我试过改用WideCharToMultiByte函数,但是依然有内存问题,google了一些帖子,好像说convertBTRToString内部也调用WideCharToMultiByte函数的。
#15
说的是啊,在主线程做同样的事情,没有任何问题,而且我还测试过,在CoInitialize函数的前面和后面都做wchar_t到char的转换,结果在调用之前成功了,而之后那个,失败了
#16
关注中~~~~~~~~~~~~~~求高手指导啊!
#17
线程套间的问题
可参考http://www.codeproject.com/KB/COM/CCOMThread2.aspx
可参考http://www.codeproject.com/KB/COM/CCOMThread2.aspx
#18
问题找到了,是我三个同时启动的线程中的一个线程中,一个char 字符串 在memset过程中size设定超过了char字符串本尊的长度,现在没问题了,还是谢谢大家