stl 清空vector容器出错

时间:2022-10-23 04:16:43
有问题的地方用红色的字体标出,请大家帮忙,谢谢
code.h:

class A
{
...
};
class B{
       public:
       ...
       vector<A> m_vect;
       }

code.cpp

vector<A> vect;
B *cp=new B();
...//cp指向了一段空间
vect=cp->m_vect;
...
//以下这三条语句,每一条都会导致报错,请教原因
vect.clear();
cp->m_vect();
delete cp;       

32 个解决方案

#1


cp->m_vect;
m_vect不是成员么?

#include <iostream>
#include <vector>
using namespace std;

class A
{
};
class B
{
public:

vector<A> m_vect;
};



int main()
{
vector<A> vect;
B *cp=new B();
//cp指向了一段空间
vect=cp->m_vect;
//以下这三条语句,每一条都会导致报错,请教原因
vect.clear();
cp->m_vect;
delete cp;

return 0;
}

#2


什么错误?是否为多线程?

#3


A和B都是Dll中得导出类。程序运行时报错,File:dbgheap.c Line:1044 Expression:_CrtIsValidHeapPointer(pUserData)

#4


上代码

#5


2楼的兄弟,是我发帖敲错了,应该是cp->m_vect.clear();

#6


A类的代码

#7


引用 3 楼 superhard_d 的回复:
A和B都是Dll中得导出类。程序运行时报错,File:dbgheap.c Line:1044 Expression:_CrtIsValidHeapPointer(pUserData)


可能是你A类没有实现好 拷贝构造函数,导致A类中有指针被反复释放造成的。最好有A类的相关代码。

#8


class A
{
public:
A(const string &a, int b):str(a), dwTime(b){}
string str;
int dwTime;
bool operator < (const A &m)const {
return dwTime< m.dwTime;
}
};

#9


我以为vector会自动为我做的,就没有实现拷贝构造函数,在使用容器的时候没有问题,就是最后释放出错了

#10


跨模块不要用STL……复杂类型。可能是你的string上的问题。报错的时候,点重试进行调试,定位到错误点就知道了。

#11


报什么错误?

#12


楼主米弄那个啥哦,(*^__^*) 嘻嘻……

#13


引用 11 楼 livpu 的回复:
报什么错误?


错误在三楼,release不报错了

#14


引用 10 楼 vcPlayer 的回复:
跨模块不要用STL……复杂类型。可能是你的string上的问题。报错的时候,点重试进行调试,定位到错误点就知道了。

调试断在dbgheap.c文件中extern "C" _CRTIMP void * __cdecl _recalloc_dbg函数最后面,搞不懂了

#15


类对象需要有拷贝构造函数才能这样相互赋值,否则出错是很正常的,没出错是侥幸。

#16


引用 15 楼 cnzdgs 的回复:
类对象需要有拷贝构造函数才能这样相互赋值,否则出错是很正常的,没出错是侥幸。

像下面这样增加了一个拷贝构造函数,仍然出错,再请教
class A
{
public:
A(const string &a, int b):str(a), dwTime(b){}
A(const A&c_p)
{
str=c_p.str;
dwTime=c_p.dwTime;
}
string str;
int dwTime;
bool operator < (const A&m)const {
return dwTime< m.dwTime;
}
}

#17


引用 15 楼 cnzdgs 的回复:
类对象需要有拷贝构造函数才能这样相互赋值,否则出错是很正常的,没出错是侥幸。

有默认的拷贝构造函数。如果类中没什么特殊的地方,就够了

#18


vs2005,mfc工程下面没有问题啊。
不会是与环境有关系吧。

#19


看来还有其它问题,省略的代码中对cp->m_vect都做了哪些操作?

#20


引用 10 楼 vcPlayer 的回复:
跨模块不要用STL……复杂类型。可能是你的string上的问题。报错的时候,点重试进行调试,定位到错误点就知道了。

同意,dll的接口参数最好不要使用STL,尤其强烈建议不要用std::string作为接口参数,MS的std::string在VC6下是有问题的(跨模块使用),不知道后续的版本是否解决了。
_CrtIsValidHeapPointer的错误很可能是vect析构的时候引起的。建议楼主看堆栈吧。这与拷贝构造没有关系。应该调用operator=函数。

#21


引用 19 楼 cnzdgs 的回复:
看来还有其它问题,省略的代码中对cp->m_vect都做了哪些操作?

没什么,和cp有关的就是在B类的一个成员函数中通过循环调用
proxyinfo tmp(temp_str,0);//temp_str是通过其他处理得到的string
m_vect.push_back(tmp);

给m_vect赋值

我使用的是vc6
引用 20 楼 turbocamel 的回复:
引用 10 楼 vcPlayer 的回复:
跨模块不要用STL……复杂类型。可能是你的string上的问题。报错的时候,点重试进行调试,定位到错误点就知道了。 
 
同意,dll的接口参数最好不要使用STL,尤其强烈建议不要用std::string作为接口参数,MS的std::string在VC6下是有问题的(跨模块使用),不知道后续的版本是否解决了。 
_CrtIsValidHeapPointer的错误很可能是vect析构的时候引起的。建议楼主看堆栈吧。这与拷贝构造没有关系。应…

是否可以说的再具体一点,谢谢

#22


vector能否直接用 "=" 复制 ??如果能是否要注意默认的vector的尺寸之类的事项?

以下是vector复制的方法:
vector <string> v1;
v1.push_back("1");
v1.push_back("2");
v1.push_back("3");

//1.
vector <string> v2(v1.begin(),v1.end());
//2.
  v2.assign(v1.begin(),v1.end());
//3.
  v2.reserve(v1.size());

//此前的1.2.3 都是在确定v2的大小.楼主选择一种加进你的代码中试试看,有效果不?
  v2=v1;//复制

#23


首先感谢22楼,试了一下,仍然是同样的错误

#24


如果只是push_back,应该没有问题,不会是遇到VC6的bug了吧。具体错误是什么?你跟踪调试看看哪里不对。

#25


vector<A> vect;
B *cp=new B();
...//cp指向了一段空间
vect=cp->m_vect;--------此时的cp->m_vect是否有元素了?每个元素是new出来的么?你是怎么添加元素的?
...
// 以下这三条语句,每一条都会导致报错,请教原因
vect.clear();----此时的vect是否有内容了
cp->m_vect();----这句不明白,干什么的?
delete cp;

#26


引用 25 楼 thomtadie 的回复:
vector <A> vect; 
B *cp=new B(); 
...//cp指向了一段空间 
vect=cp->m_vect;--------此时的cp->m_vect是否有元素了?每个元素是new出来的么?你是怎么添加元素的? 
... 
//以下这三条语句,每一条都会导致报错,请教原因 
vect.clear();----此时的vect是否有内容了 
cp->m_vect();----这句不明白,干什么的? 
delete cp;

1.这样添加的
proxyinfo tmp(temp_str,0);//temp_str是通过其他处理得到的string
m_vect.push_back(tmp);
2.我看了,有内容
3.那句发帖敲错了
应该是cp->m_vect.clear();

#27


引用 8 楼 superhard_d 的回复:
class A 

public: 
A(const string &a, int b):str(a), dwTime(b){} 
string str; 
int dwTime; 
bool operator < (const A &m)const { 
return dwTime < m.dwTime; 

};

如果A是接口类,那么这个构造函数的参数不要使用string,最好使用char*,虽然麻烦一点,但是安全。VC6下的std::string的拷贝构造和赋值函数实际上只是修改引用计数。在跨模块调用的时候会出现计数错误。另外成员也不要包含复合对象。

你把你的堆栈帖上来,让大家看看。

#28


我尝试放到vs2005上调试,把默认的unicode改成多字节了,但是生成解决方案时报错
错误3 error LNK2019: 无法解析的外部符号 "__declspec(dllimport) const  B::`vftable'" (__imp_??_7 B@@6B@),该符号在函数 "public: __thiscall  B:: B(void)" (??0B@@QAE@XZ) 中被引用 testdll.obj

红色的B是类B

#29


B是DLL的导出类?是不是项目没有导入该DLL的LIB?

#30


引用 29 楼 cnzdgs 的回复:
B是DLL的导出类?是不是项目没有导入该DLL的LIB?

是的,头文件
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
extern "C"{ 
class DECLDIR B
        {
         ...
        }
}

cpp文件

#define DLL_EXPORT
#include"xxx.h"
...
extern "C"
{

B::B()
{
}

B::~B()
{
}

#31


知道vs2005下为什么编译不过了。是虚析构函数的原因,vc6下可以,但是vs2005下会报错。但是仍然会有“dll链接不一致”的警告

#32


经测试,在vs2005下暂时没有问题,感谢大家的关注,结帖

#1


cp->m_vect;
m_vect不是成员么?

#include <iostream>
#include <vector>
using namespace std;

class A
{
};
class B
{
public:

vector<A> m_vect;
};



int main()
{
vector<A> vect;
B *cp=new B();
//cp指向了一段空间
vect=cp->m_vect;
//以下这三条语句,每一条都会导致报错,请教原因
vect.clear();
cp->m_vect;
delete cp;

return 0;
}

#2


什么错误?是否为多线程?

#3


A和B都是Dll中得导出类。程序运行时报错,File:dbgheap.c Line:1044 Expression:_CrtIsValidHeapPointer(pUserData)

#4


上代码

#5


2楼的兄弟,是我发帖敲错了,应该是cp->m_vect.clear();

#6


A类的代码

#7


引用 3 楼 superhard_d 的回复:
A和B都是Dll中得导出类。程序运行时报错,File:dbgheap.c Line:1044 Expression:_CrtIsValidHeapPointer(pUserData)


可能是你A类没有实现好 拷贝构造函数,导致A类中有指针被反复释放造成的。最好有A类的相关代码。

#8


class A
{
public:
A(const string &a, int b):str(a), dwTime(b){}
string str;
int dwTime;
bool operator < (const A &m)const {
return dwTime< m.dwTime;
}
};

#9


我以为vector会自动为我做的,就没有实现拷贝构造函数,在使用容器的时候没有问题,就是最后释放出错了

#10


跨模块不要用STL……复杂类型。可能是你的string上的问题。报错的时候,点重试进行调试,定位到错误点就知道了。

#11


报什么错误?

#12


楼主米弄那个啥哦,(*^__^*) 嘻嘻……

#13


引用 11 楼 livpu 的回复:
报什么错误?


错误在三楼,release不报错了

#14


引用 10 楼 vcPlayer 的回复:
跨模块不要用STL……复杂类型。可能是你的string上的问题。报错的时候,点重试进行调试,定位到错误点就知道了。

调试断在dbgheap.c文件中extern "C" _CRTIMP void * __cdecl _recalloc_dbg函数最后面,搞不懂了

#15


类对象需要有拷贝构造函数才能这样相互赋值,否则出错是很正常的,没出错是侥幸。

#16


引用 15 楼 cnzdgs 的回复:
类对象需要有拷贝构造函数才能这样相互赋值,否则出错是很正常的,没出错是侥幸。

像下面这样增加了一个拷贝构造函数,仍然出错,再请教
class A
{
public:
A(const string &a, int b):str(a), dwTime(b){}
A(const A&c_p)
{
str=c_p.str;
dwTime=c_p.dwTime;
}
string str;
int dwTime;
bool operator < (const A&m)const {
return dwTime< m.dwTime;
}
}

#17


引用 15 楼 cnzdgs 的回复:
类对象需要有拷贝构造函数才能这样相互赋值,否则出错是很正常的,没出错是侥幸。

有默认的拷贝构造函数。如果类中没什么特殊的地方,就够了

#18


vs2005,mfc工程下面没有问题啊。
不会是与环境有关系吧。

#19


看来还有其它问题,省略的代码中对cp->m_vect都做了哪些操作?

#20


引用 10 楼 vcPlayer 的回复:
跨模块不要用STL……复杂类型。可能是你的string上的问题。报错的时候,点重试进行调试,定位到错误点就知道了。

同意,dll的接口参数最好不要使用STL,尤其强烈建议不要用std::string作为接口参数,MS的std::string在VC6下是有问题的(跨模块使用),不知道后续的版本是否解决了。
_CrtIsValidHeapPointer的错误很可能是vect析构的时候引起的。建议楼主看堆栈吧。这与拷贝构造没有关系。应该调用operator=函数。

#21


引用 19 楼 cnzdgs 的回复:
看来还有其它问题,省略的代码中对cp->m_vect都做了哪些操作?

没什么,和cp有关的就是在B类的一个成员函数中通过循环调用
proxyinfo tmp(temp_str,0);//temp_str是通过其他处理得到的string
m_vect.push_back(tmp);

给m_vect赋值

我使用的是vc6
引用 20 楼 turbocamel 的回复:
引用 10 楼 vcPlayer 的回复:
跨模块不要用STL……复杂类型。可能是你的string上的问题。报错的时候,点重试进行调试,定位到错误点就知道了。 
 
同意,dll的接口参数最好不要使用STL,尤其强烈建议不要用std::string作为接口参数,MS的std::string在VC6下是有问题的(跨模块使用),不知道后续的版本是否解决了。 
_CrtIsValidHeapPointer的错误很可能是vect析构的时候引起的。建议楼主看堆栈吧。这与拷贝构造没有关系。应…

是否可以说的再具体一点,谢谢

#22


vector能否直接用 "=" 复制 ??如果能是否要注意默认的vector的尺寸之类的事项?

以下是vector复制的方法:
vector <string> v1;
v1.push_back("1");
v1.push_back("2");
v1.push_back("3");

//1.
vector <string> v2(v1.begin(),v1.end());
//2.
  v2.assign(v1.begin(),v1.end());
//3.
  v2.reserve(v1.size());

//此前的1.2.3 都是在确定v2的大小.楼主选择一种加进你的代码中试试看,有效果不?
  v2=v1;//复制

#23


首先感谢22楼,试了一下,仍然是同样的错误

#24


如果只是push_back,应该没有问题,不会是遇到VC6的bug了吧。具体错误是什么?你跟踪调试看看哪里不对。

#25


vector<A> vect;
B *cp=new B();
...//cp指向了一段空间
vect=cp->m_vect;--------此时的cp->m_vect是否有元素了?每个元素是new出来的么?你是怎么添加元素的?
...
// 以下这三条语句,每一条都会导致报错,请教原因
vect.clear();----此时的vect是否有内容了
cp->m_vect();----这句不明白,干什么的?
delete cp;

#26


引用 25 楼 thomtadie 的回复:
vector <A> vect; 
B *cp=new B(); 
...//cp指向了一段空间 
vect=cp->m_vect;--------此时的cp->m_vect是否有元素了?每个元素是new出来的么?你是怎么添加元素的? 
... 
//以下这三条语句,每一条都会导致报错,请教原因 
vect.clear();----此时的vect是否有内容了 
cp->m_vect();----这句不明白,干什么的? 
delete cp;

1.这样添加的
proxyinfo tmp(temp_str,0);//temp_str是通过其他处理得到的string
m_vect.push_back(tmp);
2.我看了,有内容
3.那句发帖敲错了
应该是cp->m_vect.clear();

#27


引用 8 楼 superhard_d 的回复:
class A 

public: 
A(const string &a, int b):str(a), dwTime(b){} 
string str; 
int dwTime; 
bool operator < (const A &m)const { 
return dwTime < m.dwTime; 

};

如果A是接口类,那么这个构造函数的参数不要使用string,最好使用char*,虽然麻烦一点,但是安全。VC6下的std::string的拷贝构造和赋值函数实际上只是修改引用计数。在跨模块调用的时候会出现计数错误。另外成员也不要包含复合对象。

你把你的堆栈帖上来,让大家看看。

#28


我尝试放到vs2005上调试,把默认的unicode改成多字节了,但是生成解决方案时报错
错误3 error LNK2019: 无法解析的外部符号 "__declspec(dllimport) const  B::`vftable'" (__imp_??_7 B@@6B@),该符号在函数 "public: __thiscall  B:: B(void)" (??0B@@QAE@XZ) 中被引用 testdll.obj

红色的B是类B

#29


B是DLL的导出类?是不是项目没有导入该DLL的LIB?

#30


引用 29 楼 cnzdgs 的回复:
B是DLL的导出类?是不是项目没有导入该DLL的LIB?

是的,头文件
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
extern "C"{ 
class DECLDIR B
        {
         ...
        }
}

cpp文件

#define DLL_EXPORT
#include"xxx.h"
...
extern "C"
{

B::B()
{
}

B::~B()
{
}

#31


知道vs2005下为什么编译不过了。是虚析构函数的原因,vc6下可以,但是vs2005下会报错。但是仍然会有“dll链接不一致”的警告

#32


经测试,在vs2005下暂时没有问题,感谢大家的关注,结帖