我的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。
答案 0 :(得分:5)
使用C编译器编译 main.c 时,它将不具有newA
,deleteA
或update
函数的声明(它们被#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