可重复的:为什么通过这个对象用C打破我的code? [英] Reproducible: Why does passing this object in C break my code?

查看:109
本文介绍了可重复的:为什么通过这个对象用C打破我的code?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从我的理解ç假定所有的参数都是诚信的,并返回整数。我想通过解决此对象,但我不知道它是如何和AFAIK它为int的大小相同,但破坏。这里是重现code。

在testc.c。注:这必须是在C文件

  INT test_c1(){
    返回test_c3(test_c2());
}

在testcpp.cpp

 的#include<&iostream的GT;
使用命名空间std;
结构的MyType {
    诠释A,B;
};模板<类T>
结构WrappedPointer {
    T * LHS;
上市:
    无效LHS(T * V){LHS = V; }
    T * LHS(){返回LHS; }
    WrappedPointer(){}
    WrappedPointer(T *值):LHS(值){}
    WrappedPointer(常量WrappedPointer&放大器;ⅴ):LHS(v.lhs){}
    T *操作符>()const的{返回LHS; }
    T *的operator *()const的{返回LHS; }
};
typedef的WrappedPointer<&MyType的GT; ObjPtr;
static_assert(的sizeof(ObjPtr)==的sizeof(INT),);
static_assert(的sizeof(ObjPtr)==的sizeof(void *的),);为externC{
    ObjPtr test_c1();
    ObjPtr test_c2(){
        // ObjPtr S = 0;
        ObjPtr S;
        s.LHS(0);
        COUT&所述;&下;C2&所述;&下; s.LHS()&所述;&下; ENDL;
        返回S;
    }
    ObjPtr test_c3(ObjPtr V){
        COUT<<C3<< v.LHS()&所述;&下; ENDL;
        返回伏;
    }
};诠释主(){
    汽车V = test_c1();
    COUT<<主<< v.LHS()&所述;&下; ENDL;
}

GCC编译标志

 的gcc -Wall -c testc.c
testc.c:在函数'test_c1:
testc.c:2:2:警告:函数'test_c3'隐式声明[-Wimplicit功能声明]
testc.c:2:2:警告:函数'test_c2'隐式声明[-Wimplicit功能声明]
G ++ -std =的C ++ 0x -Wall -c testcpp.cpp
G ++ testc.o testcpp.o
A.EXE

应该崩溃,因为你可以看到我所得到的唯一的警告是功能隐含:(。为什么崩溃?尤其是当我断言, ObjPtr 是的确是相同的大小为int。我如何解决这个问题,使我可以绕过ObjPtr?我不能修改的C库这样testc.c是关闭的限制。

-edit-,而不是在VS 2010中崩溃我得到这个打印输出,显示传递的对象是不正确。我不明白的地方B来自于结束。这发生在调试模式。发布崩溃与访问冲突。

  C2 00000000
C3 0046F8B0
主要CCCCCCCC

preSS任意键继续。 。 。

如果你好奇,如果你注释掉的构造函数(并更改没有别的),这将在海湾合作委员会的工作。如果你改变全班分成结构所以没有成员是私有的,将在msvc2010工作。此修复程序是废话,但似乎其考虑POD,当我做到这一点,神奇的code ++工程。因为在C中的定义并没有改变这是怪(因为没有定义)。和构造函数都没有做什么不同。


解决方案

  

从我的理解ç假定所有的参数都是诚信的,并返回整数。


不完全是。

在此之前的1999 ISO C标准,调用一个函数没有可见的声明会导致编译器认为它返回一个类型 INT 的结果。这并不适用于参数;他们假设参数(S)的(推动)型(S)的,如果有的话。

C99放弃了隐式int类型的规则;调用一个函数没有可见的声明是一个约束冲突,这基本上意味着它是非法的。它甚至不是在pre-1999 C是一个好主意。

如果你打算从C调用C ++,你调用任何函数应该有参数和返回了与两种语言兼容的类型。 C没有类或模板,所以有一个C程序中调用C ++函数返回一个 WrappedPointer< MyType的方式> 至少是可疑的。

假设指针的大小 INT 同样使你的code极不便于携带。即使他们是相同的大小,它们是不能互换; INT 和指针函数结果可能会使用不同的机制来返回(不同的CPU寄存器,例如)。

我建议有 test_c1() test_c2()收益无效* ,它可以指向任何类型的对象。和C源需要有它调用的任何函数可见声明(preferably原型)。

From my understanding C assumes all parameters are int's and it returns ints. I'd like to pass around this object but i have no idea how and AFAIK its the same size of int but it breaks. Here is the Reproducible code.

In testc.c. Note: this MUST be in a C file.

int test_c1() {
    return test_c3(test_c2());
}

In testcpp.cpp

#include <iostream>
using namespace std;
struct MyType{
    int a, b;
};

template <class T>
struct WrappedPointer {
    T* lhs;
public:
    void LHS(T*v) { lhs=v; }
    T*   LHS() { return lhs; }
    WrappedPointer(){}
    WrappedPointer(T*value) : lhs(value){}
    WrappedPointer(const WrappedPointer&v) : lhs(v.lhs){}
    T* operator->() const { return lhs; }
    T* operator*() const { return lhs; }
};
typedef WrappedPointer<MyType> ObjPtr;
static_assert(sizeof(ObjPtr) == sizeof(int), "");
static_assert(sizeof(ObjPtr) == sizeof(void*),"");

extern "C" {
    ObjPtr test_c1();
    ObjPtr test_c2() {
        //ObjPtr s=0;
        ObjPtr s;
        s.LHS(0);
        cout <<"c2 " << s.LHS() << endl;
        return s; 
    }
    ObjPtr test_c3(ObjPtr v) { 
        cout <<"c3 " << v.LHS() << endl;
        return v; 
    }
};

int main() {
    auto v = test_c1();
    cout <<"main " << v.LHS() << endl;
}

gcc compile flags

gcc -Wall -c testc.c
testc.c: In function 'test_c1':
testc.c:2:2: warning: implicit declaration of function 'test_c3' [-Wimplicit-function-declaration]
testc.c:2:2: warning: implicit declaration of function 'test_c2' [-Wimplicit-function-declaration]
g++ -std=c++0x -Wall -c testcpp.cpp
g++ testc.o testcpp.o
a.exe

It should crash and as you can see the only warning i ever got was the function is implicit :(. Why does a crash? especially when i asserted that ObjPtr is indeed the same size as int. How do i fix this so that i can pass around ObjPtr? I CAN NOT modify the C library so testc.c is off limits.

-edit- instead of crashing in VS 2010 i get this printout which shows the passed object is incorrect. I don't understand where "B" comes from at the end. This happens in debug mode. Release crashes with access violation.

c2 00000000
c3 0046F8B0
main CCCCCCCC
B
Press any key to continue . . .

If your curious, if you comment out the constructors (and change nothing else) this will work in gcc. If you change class into struct so no member is private it will work in msvc2010. This fix is nonsense but it appears its consider POD when i do this and magically the code works. Which is weird since the definition in C hasn't changed (as there is no definition). And the constructors aren't doing anything different.

解决方案

From my understanding C assumes all parameters are int's and it returns ints.

Not quite.

Prior to the 1999 ISO C standard, calling a function without a visible declaration would cause the compiler to assume that it returns a result of type int. This does not apply to parameters; they're assumed to be of the (promoted) type(s) of the argument(s), if any.

C99 dropped the "implicit int" rule; calling a function without a visible declaration is a constraint violation, which basically means that it's illegal. It's not a good idea even in pre-1999 C.

If you're going to call C++ from C, any functions you call should have parameter and return types that are compatible with both languages. C doesn't have classes or templates, so having a C program call a C++ function that returns a WrappedPointer<MyType> is at least questionable.

Assuming that pointers are the same size as int makes your code extremely non-portable. Even if they're the same size, they're not interchangeable; int and pointer function results might be returned using different mechanisms (different CPU registers, for example).

I suggest having test_c1() and test_c2() return void*, which can point to an object of any type. And your C source needs to have visible declarations (preferably prototypes) for any functions it calls.

这篇关于可重复的:为什么通过这个对象用C打破我的code?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆