C ++类的C包装器返回错误的地址

时间:2017-04-19 08:35:37

标签: c++ c

我的C ++标题是

header.hh

#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
#include <string>
class A
{
    uint32_t a;
    public: 
        A(){
           a = 0;
        }
        void update(uint32_t b) {
           a = b;
        }
};
#else
typedef struct A A;
#endif //__cplusplus
#ifdef __cplusplus
extern "C" {
    void* newA(void);
    void deleteA(A* a);
    void update(A*a,uint32_t b);
}
#endif

我的c ++文件是

class.cc

#include "header.hh"
#include <iostream>
extern "C" {
    void* newA(void) {
        A* a = new A();
        return (reinterpret_cast <void*> (a));
    }
    void deleteA(A* a) {
         delete a;
    }
    void update(A* a,uint32_t b){
        a->update(b);
    }
}

的main.c

#include "header.hh"
#include <stdio.h>
int main()
{
    A* a = (A*) newA();
    deleteA(a);
}

生成文件

CFLAGS=-Wall -g -ansi -pedantic -std=c99
CCFLAGS=-Wall -g
LDFLAGS=-g -Wall -lstdc++

OBJS=class.o main.o
PROG=test

all:$(PROG)
default: all

%.o: %.cc
    $(CC) $(CCFLAGS) -c $<

%.o: %.c
    $(CC) $(CFLAGS) -c $<

$(PROG): $(OBJS)
    $(CC) $(OBJS) $(LDFLAGS) -o $@

clean:
    rm -rf $(OBJS)
    rm -rf $(PROF)

当我编译并运行这个程序时,当我尝试在Main中调用析构函数时,我看到了一个段错误。

我进入gdb并发现class.cc中“a”的地址为 0x7fff980097a0 ,而main中的地址为 0xffffffff980097a0

导致地址变更的原因是什么?

我在ubuntu 14.04上使用4.8.4版本的gcc。

2 个答案:

答案 0 :(得分:5)

使用C编译器编译 main.c 时,它将不具有newAdeleteAupdate函数的声明(它们被#ifdef __cplusplus包围。

因此,它将采用默认签名int newA()(与其他两个类似)。

这意味着在这一行:

A* a = (A*) newA();

newA()返回的值被视为int,然后转换为A*。将int强制转换为指针类型的结果是实现定义的。在您的平台上,您的行为似乎就是您所观察到的。

最有可能的是,在您的平台上,sizeof(int)4,而sizeof(void*)8。在这种情况下,0x7fff980097a0在被视为0x980097a0时被截断为int,然后在投放到0xffffffff980097a0时扩展为A*。这正是你所观察到的。

相反,请尝试使C语言编译器可以看到声明:

#ifdef __cplusplus
extern "C" {
#endif
    void* newA(void);
    void deleteA(A* a);
    void update(A*a,uint32_t b);
#ifdef __cplusplus
}
#endif

答案 1 :(得分:1)

在标题中:

#ifdef __cplusplus
extern "C" {
#endif 

// The header declaration is included both by the the C and the C++ 
// compiler.

void* newA(void);
void deleteA(A* a);
void update(A*a,uint32_t b);

#ifdef __cplusplus
} 
#endif