【发布时间】:2012-03-10 03:33:22
【问题描述】:
-edit- 我缩小了范围。 Reproducible: Why does passing this object in C break my code?
在我进行更改后,我的应用程序无法正常运行。我在 msvc 中收到警告,但在 gcc 中没有。 这是警告的回购。
警告 C4190:'fnA' 指定了 C 链接,但返回与 C 不兼容的 UDT 'Test'
#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 大于 8 字节,我需要将它交给 C 代码,不幸的是,它返回所有内容。这就是为什么我放置静态断言来查看班级规模是否符合我的预期。既然处理了尺寸/拼接,我还是完全喜欢WTF!?!为什么会出现该警告?有什么办法可以解决吗?
即使写 class Test{ T t; }; 也会导致警告,但 struct 会修复它。带有私有的结构会破坏它,我需要保持私有。
好的!在我删除 WrappedPointer 中的构造函数并将类更改为 struct (这使得 lhs 公开)之后。它在 GCC 和 MSVC 中完美运行。将 struct WrappedPointer 更改为 class WrappedPointer 会破坏我的代码。哇!?!这也是一个调试版本,没有优化。为什么将关键字 struct 更改为 class 会破坏代码!?!哇!?!但是这个改变并没有破坏 gcc。使用非默认构造函数会破坏 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*),"");
【问题讨论】:
-
调用
fnA的C代码对它接收到的对象做了什么?由于 C 中没有类,因此您应该编写一个不返回类的函数并在 C 代码中使用它。 -
@jogojapan:fnA 只是导致错误的一个例子。你是什么意思不返回一个类!?!你是说把它放在一个全局变量中!?!也没用,因为代码可能会在调用我的代码之前多次调用此函数。
-
我的意思是:在
external "C"中使用C++ 是可以的,但是如果你在那里使用的C++ 类型最终返回到C 代码,应该怎么做? C代码对它们做什么?它不能处理一个类。 -
根据here,如果函数的定义是在C++中,代码是合法的,但不是。
-
@Jesse 还有第二个条件:“对这个函数的所有调用都来自 C++。”我的理解是必须满足两个条件。还有,函数is在C++中的定义不是吗。
标签: c++ crash undefined-behavior