【发布时间】:2018-12-22 11:10:24
【问题描述】:
我定义了一个联合结构,可以在字符串指针或长指针之间切换(这是由于对齐问题)。结构本身如下所示。
enum {H_STRING, H_LONG};
union Tag
{
std::string *path;
long id;
};
struct TextureID
{
Tag tag;
int type=H_STRING;
TextureID()
{
type = H_STRING;
tag.path = new std::string("");
}
TextureID(const TextureID& TID)
{
type = TID.type;
if(type==H_STRING)
tag.path = new std::string(*(TID.tag.path));
else
tag.id = TID.tag.id;
}
~TextureID()
{
delete(tag.path);
}
TextureID& operator= (std::string str)
{delete(tag.path); tag.path = new std::string(str); type=H_STRING; return *this;}
TextureID& operator= (long val)
{ if(type==H_STRING) delete(tag.path); tag.id = val; type=H_LONG; return *this;}
operator std::string&()
{
if(type == H_STRING)
{
return *(tag.path);
}
}
};
std::istream inline &operator>> (std::istream& is, TextureID& TID)
{is >> *(TID.tag.path); TID.type = H_STRING; return is;}
std::ostream inline &operator<< (std::ostream& os, TextureID& TID)
{return os << *(TID.tag.path);}
使用 valgrind,我确定这个数据结构存在内存泄漏。
验证这个结构是内存泄漏原因的方法(即我确定这是原因而不是其他原因的原因)是重载当前正在使用的所有运算符(=,> ) 并且有两个版本的数据结构。第一个是您在上面看到的使用联合的那个。第二个只是在 TextureID 中有一个字符串和一个长 2 个单独的字段。
第二个实现(不使用指针的那个)没有内存泄漏。
我知道如果标签设置为长,这可能会导致分段错误。这不是问题,问题是不知何故,尽管有对 delete() 的显式调用,但分配的内存没有被删除(目前程序中没有任何内容将标记值设置为 long,因此也不会发生 seg 错误)。
编辑:
有人要求我提供内存泄漏证明,所以这里是:
此版本不会导致内存泄漏:
enum {H_STRING, H_LONG};
struct TextureID
{
std::string path;
long ID;
int type=H_STRING;
TextureID& operator= (std::string str)
{path = str;}
TextureID& operator= (long val)
{ID = val;}
operator std::string&()
{
if(type == H_STRING)
{
return (path);
}
}
};
std::istream inline &operator>> (std::istream& is, TextureID& TID)
{is >> TID.path; return is;}
std::ostream inline &operator<< (std::ostream& os, TextureID& TID)
{return os << TID.path;}
【问题讨论】:
-
请注意,在现代 c++ 中,您可以使用
alignas(long)表示“我希望它像长条一样对齐”(en.cppreference.com/w/cpp/language/alignas) -
@OlivierSohn 您可以将长字符串(8 字节)对齐(32 字节)吗?我不确定我是否理解。
-
是的,链接里有说明,可以在成员声明前加上
alignas(...),比如:alignas(long) std::string myString; -
关于内存泄漏,您能否提供一个显示内存泄漏的程序(带有主程序)的最小示例?
-
@Makogan 您的
struct缺少赋值运算符。因此{TextureID t1; TextureID t2; t1 = t2;}会出错。
标签: c++ pointers memory memory-leaks unions