问题描述
-edit-我缩小了范围。
-edit- I narrowed it down. Reproducible: Why does passing this object in C break my code?
我进行更改后,我的应用无法正常运行。我在msvc中收到了警告,但在gcc中却没有。
这是警告的回购。
My app is not working properly after i made a change. I got a warning in msvc but not in gcc.Heres a repo of the warning.
#include <type_traits>
template<class T>
class Test{
T t;
};
typedef Test<int> A;
//static_assert(std::is_pod<A>::value, "Not a POD"); //fails in msvc 2010
static_assert(sizeof(A) == sizeof(int), "");
static_assert(sizeof(A) == sizeof(void*), "");
extern "C" {
A fnA(A v) { return v; }
}
int main() {
A a;
fnA(a);
}
AFAIK我应该没有理由不能使用Test作为回报值;这可能不是问题,但这可能是问题。我无法解决问题,但遇到无法重现的运行时异常(gcc和msvc)。我怀疑问题可能是MyString损坏了,但事实并非如此,这让我很困惑。这是我的包装纸。 MyString> 8bytes,我需要将此交给C代码,不幸的是,它会通过int返回所有内容。这就是为什么我放静态断言来查看类大小是否是我期望的。现在可以处理大小/拼接了,我仍然完全像WTF!?!为什么存在该警告,并且我有什么可以解决的方法?
AFAIK there should be no reason why i can't use Test as a return value; This may not be the problem but this may be the problem. I can't figure out the problem but i get runtime oddities that i can not reproduce (both gcc and msvc). I suspected the problem would be MyString is corrupted but it appears that isnt the case which made me quite confused. Heres my wrapper. MyString is >8bytes and i need to hand this off to C code which returns everything by int unfortunately. Which is why i put the static assert to see if the class size is what i expected. Now that size/splicing is handled, i'm still completely like WTF!?! Why does that warning exist and is there anything i can possibly do to fix it?
即使编写 class Test {T t; };
会导致警告,但是struct对其进行了修复。
Even writing class Test{ T t; };
causes the warning however struct fixes it. struct with private breaks it and i need t to be private.
好!在删除WrappedPointer中的构造函数并将类更改为struct之后(将lhs设为公共)。它可以在GCC和MSVC中完美运行。将 struct WrappedPointer
更改为 Class WrappedPointer
会破坏我的代码。 WTF!?!这也是调试版本,未优化。到底为什么将关键字struct更改为class会破坏代码!?! WTF!?!但这种改变不会破坏gcc。使用非默认构造函数破坏gcc ...
OK! After I removed the constructors in WrappedPointer and changed the class to struct (which makes lhs public). It runs perfectly in GCC and MSVC. Changing struct WrappedPointer
to class WrappedPointer
breaks my code. WTF!?! This is a debug build too, not optimized. Why on earth does changing the keyword struct to class break the code!?! WTF!?! BUT that change doesnt break gcc. Using non default constructors break gcc...
template <class T>
struct WrappedPointer {
//private:
T* lhs;
public:
void SetLHS(T*v) { lhs=v; }
//WrappedPointer(){}
//WrappedPointer(T*value) : lhs(value){}
//WrappedPointer(const WrappedPointer&v) : lhs(v.lhs){}
T* operator->() const { return lhs; }
T* operator*() const { return lhs; }
template<class TT>
bool operator==(TT t) const { return *lhs==t; }
template<class TT>
bool operator!=(TT t) const { return *lhs!=t; }
bool operator==(int v) const { myassert2(v==0); return lhs==0; }
bool operator!=(int v) const { myassert2(v==0); return lhs!=0; }
bool operator==(const WrappedPointer&t) const { return *lhs==*t; }
bool operator!=(const WrappedPointer&t) const { return *lhs!=*t; }
}
typedef WrappedPointer<MyString> String;
//typedef MyString* String;
static_assert(sizeof(String) == sizeof(int), "");
static_assert(sizeof(String) == sizeof(void*),"");
推荐答案
外部 C
标记具有C链接的功能,并且禁用名称修饰。现在您函数中的问题是参数是一个 template ( typedef
仅在当前翻译单元<$ c $中创建一个别名。 c> A 仍然是 Test< int>
),并且该名称必须修改。
The external "C"
marks the function to have C linkage and disables name mangling. Now the issue in your function is that the argument is a template (the typedef
only creates an alias in the current translation unit, A
is still Test<int>
for all purposes), and that name must be mangled.
这篇关于我的代码可能因为“类”与C不兼容而崩溃了?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!