以下代码编译没有错误。基本上,C#2005控制台应用程序调用VC ++ 2005类库,后者又调用本机VC ++ 6代码。运行C#2005应用程序时出现以下错误:
“未处理的异常:System.AccessViolationException:尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”
此错误的原因是什么?以及如何纠正它?
Edit1:它在 StdStringWrapper ssw = w.GetNext();
行崩溃Edit2:我遵循Naveen的建议并使用整数索引而不是迭代器,现在没有更多错误。非常感谢所有评论的人!
C#2005中编写的代码作为控制台应用程序:
class Program
{
static void Main(string[] args)
{
Class1 test= new Class1();
test.PerformAction();
test.PerformAction();
test.PerformAction();
test.PerformAction();
}
}
VC ++ 2005中编写的代码类库:
public ref class Class1
{
public:
void PerformAction();
};
void Class1::PerformAction()
{
DoSomethingClass d;
StdStringContainer w;
d.PerformAction(w);
for(int i=0; i<w.GetSize(); i++)
{
StdStringWrapper ssw = w.GetNext();
std::cout << ssw.CStr() << std::endl;
}
}
VC ++ 6中编写的代码作为动态链接库:
#ifdef NATIVECODE_EXPORTS
#define NATIVECODE_API __declspec(dllexport)
#else
#define NATIVECODE_API __declspec(dllimport)
#endif
class NATIVECODE_API StdStringWrapper
{
private:
std::string _s;
public:
StdStringWrapper();
StdStringWrapper(const char *s);
void Append(const char *s);
const char* CStr() const;
};
StdStringWrapper::StdStringWrapper()
{
}
StdStringWrapper::StdStringWrapper(const char *s)
{
_s.append(s);
}
void StdStringWrapper::Append(const char *s)
{
_s.append(s);
}
const char* StdStringWrapper::CStr() const
{
return _s.c_str();
}
//
class NATIVECODE_API StdStringContainer
{
private:
std::vector<StdStringWrapper> _items;
std::vector<StdStringWrapper>::iterator _it;
public:
void Add(const StdStringWrapper& item);
int GetSize() const;
StdStringWrapper& GetNext();
};
void StdStringContainer::Add(const StdStringWrapper &item)
{
_items.insert(_items.end(),item);
}
int StdStringContainer::GetSize() const
{
return _items.size();
}
StdStringWrapper& StdStringContainer::GetNext()
{
std::vector<StdStringWrapper>::iterator it = _it;
_it++;
return *it;
}
//
class NATIVECODE_API DoSomethingClass
{
public:
void PerformAction(StdStringContainer &s);
};
void DoSomethingClass::PerformAction(StdStringContainer &s)
{
StdStringWrapper w1;
w1.Append("This is string one");
s.Add(w1);
StdStringWrapper w2;
w2.Append("This is string two");
s.Add(w2);
}
答案 0 :(得分:1)
_it
中的成员StdStringContainer
从未初始化为指向_items
向量。这意味着它是一个无效的迭代器。当您在_it
中将it
分配给GetNext()
时,您已it
提供_it
中存在的无效,未初始化的值。然后通过_it
递增未初始化的_it++
,这就是触发你的错误。
正如Stroustrup在19.2中所说,未初始化的迭代器是一个无效的迭代器。这意味着您的未初始化_it
无效,并且使用它执行的操作未定义,可能会导致严重失败。
然而,你的问题更深层次。迭代器与它们枚举的容器的生命周期根本不同。除非容器是不可变的并且在构造函数中初始化,否则实际上没有任何“好”方法可以用这样的迭代器成员执行。
如果你不能公开std :: namespace名称,你是否考虑过通过typedef对它们进行别名,例如?您的组织或项目怎么样才能公开模板类?
答案 1 :(得分:0)
听起来你有内存泄漏。我建议寻找有指针算术,写入内存或数组使用的任何地方。检查数组访问中的边界条件。
另一个问题:泄漏许多甚至不在您的代码中。如果是这种情况,您将不得不从项目中排除库。
答案 2 :(得分:0)
从我的角度来看,主要问题是您在iterator
课程中将vector
存储到stdStringContainer
。请记住,每当向量调整大小时,所有现有的迭代器都将失效。因此,每当您向向量中插入操作时,它可能会调整大小并且您的现有迭代器变为无效。如果您尝试在GetNext()
中取消引用它,那么它将访问无效的内存位置。为了检查是否真的如此,尝试将初始向量大小保留为某个相对较大的数字,以便不会发生调整大小。您可以使用reserve()
方法保留大小,在这种情况下,可以保证向量的capacity()
大于或等于保留值。
答案 3 :(得分:0)
我的猜测是,你遇到了崩溃,因为两个C ++模块之间的接口中的std::string
和std::vector
是用不同的编译器和运行时库编译的。
矢量和字符串的内存布局可能会在VC6和2005之间发生变化。
当2005 DLL分配类型为StdStringContainer
和StdStringWrapper
的对象时,它会根据2005标题中string
和vector
的声明进行分配。
当在这些对象(使用VC6编译器和库编译)上调用成员函数时,它们会采用不同的内存布局,并且会因访问冲突而失败。