简体   繁体   English

自定义容器与g ++(Rstudio)兼容,不适用于MSVS 2012

[英]Customized container works fine with g++(Rstudio), not fine with MSVS 2012

I have a piece of C++ test code that works fine in Rstudio, which uses g++, but will result in run-time error in MSVS 2012: 我有一段C ++测试代码可以在Rstudio(使用g ++)中正常运行,但会在MSVS 2012中导致运行时错误:

template<typename T>
struct vec{
    T*head, *tail;
    vec()
    {
        head=NULL;
        tail=NULL;
    }
    vec(int n)
    {
        head=(T*)malloc(sizeof(T)*n);
        tail=head+n;
    }
    T operator [] (int i) const {return *(head+i);}
    T & operator [] (int i) {return *(head+i);}
    ~vec(){free(head);}
};

int main(){
    std::vector<int>y(3);
    y[0]=1; y[1]=2; y[2]=3;
    vec<int>x1(3);
    x1[0]=y[0];
    std::cout<<"vec of integers, [] overloading works fine \n";
    std::vector<std::vector<int>::iterator>z(3);
    z[0]=y.begin();
    z[1]=y.begin()+1;
    z[2]=y.begin()+2;
    vec<std::vector<int>::iterator>x2(3);
    x2[0]=z[0];
    std::cout<<*x2[0]<<"\n";
    std::cout<<"vec of std::vector::iterator, [] overloading g++ works fine, MSVS doesn't \n";
    return 1;
}

The code shows if vec contains integers, both MSVS and Rstudio work fine; 代码显示vec是否包含整数,MSVS和Rstudio都可以正常工作; if vec contains iterators, MSVS will run into the following error: 如果vec包含迭代器,则MSVS将遇到以下错误:

在此处输入图片说明

I sensed it has something to do with iterators. 我感觉到它与迭代器有关。 Could anyone let me know where my mistake is? 谁能让我知道我的错误在哪里? Btw, I only included the vector header file in MSVS. 顺便说一句,我只在MSVS中包含了向量头文件。

Thanks! 谢谢!

VS has additional error checking baked in to its iterators in debug mode. VS在调试模式下将附加的错误检查添加到其迭代器中。 It found a legitimate bug in your code! 它在您的代码中发现了一个合法的错误! The error is that you reinterpret uninitialized memory as initialized objects: 错误是您将未初始化的内存重新解释为已初始化的对象:

vec(int n){head=(T*)malloc(sizeof(T)*n);tail=head+n;}
                ^^^^^^^^^^^^^^^^^^^^^^^

T & operator [] (int i) {return *(head+i);}
                                ^^^^^^^^^

x2[0]=z[0];
^^^^^^

The assignment calls operator= on the vector iterator object, which is really uninitialized memory, which leads to the crash you're seeing when it tries to interpret some of that memory as valid data. 分配在向量迭代器对象上调用operator= ,该对象实际上是未初始化的内存,当您尝试将某些内存解释为有效数据时,会导致崩溃。 (0xCDCDCDCD, by the way, is what the debugger commonly fills uninitialized memory with to help catch these kind of bugs quicker.) (顺便说一下,调试器通常使用0xCDCDCDCD来填充未初始化的内存,以帮助更快地捕获此类错误。)

I suggest using new / delete instead of malloc. 我建议使用new / delete而不是malloc。 Raw memory allocation is tricky to get right in C++ (where normal memory management is already plenty hard enough). 原始内存分配很难在C ++中正确实现(常规内存管理已经足够困难)。

Note also that in the general case, malloc may not yield blocks with high enough alignment for all object types (although it will most of the time, since very few objects are aligned to more than 16 bytes). 还要注意,在一般情况下,对于所有对象类型, malloc可能不会产生具有足够高对齐方式的块(尽管大多数情况下会这样做,因为很少有对象对齐到超过16个字节)。

You are allocating (uninitialized) memory using malloc and trying to interpret it as non-POD types like iterators can be. 您正在使用malloc分配(未初始化的)内存,并试图像迭代器一样将其解释为非POD类型。 This is bound to fail - operator= for an object expects an initialized object as its left operand, but you are giving it a garbage value (hence the crash). 这势必会失败-一个对象的operator=期望将一个初始化的对象作为其左操作数,但是您要给它一个垃圾值(因此崩溃)。

Also, you are not calling your elements' destructors, since you use plain free . 另外,由于您使用的是plain free ,因此您不会调用元素的析构函数。

A simple solution is to use new T[n] in your constructor instead of malloc (and delete[] in the destructor). 一个简单的解决方案是在构造函数中使用new T[n]而不是malloc (在析构函数中使用delete[] )。 This requires your T to be default-constructible; 这要求您的T必须是默认可构造的; there are ways to weaken this requirement (involving placement new and some tricks to guarantee alignment). 有多种方法可以削弱此要求(涉及new展示位置以及一些确保对齐的技巧)。

By the way, your vec class does not implement neither the "rule of three" nor the "rule of five", neither disables copy construction, so you are going to have double frees in case your vec object is ever copied. 顺便说一句,您的vec类既未实现“三个规则”也未实现“五个规则”,也没有禁用复制构造,因此,如果曾经复制了vec对象,您将拥有两次释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM