取消引用会导致Segmentation错误

dereferencing this causes Segmentation fault

本文关键字:Segmentation 错误 引用 取消      更新时间:2023-10-16

我有以下函数

LinearScheme::LinearScheme() {
cout << " empty constructor" << endl;
}

void LinearScheme::init(
int tableId,
std::string &basePath,
std::vector<size_t> &colElemSizes,
TupleDescMap &tupleDescMap,
size_t defaultMaxFragmentSize,
int numCols,
BoundBases &bounds,
std::vector<int> &colsPartitioned ) 
{
// This linear scheme ignores bounds
// it could be improved to use colsPartitioned for ordering (TODO)
cout << "init Linear Scheme " << endl;
*this = LinearScheme(); //SEGFAULTS HERE
cout << "after cons here?" << endl;
// init private fields    
this->tableId_ = tableId;
this->basePath_ = basePath;
this->colElemSizes_ = colElemSizes;
this->numCols_ = numCols;
this->tupleDescMap_ = tupleDescMap;
this->numFragments_ = 0;
this->defaultMaxFragmentSize_ = defaultMaxFragmentSize;
// fragmentSizesFilename_ init    
fragmentSizesFilename_  = basePath_ + boost::lexical_cast <string>(tableId_)
+ "_cs";
struct stat st;
// open existing file if exists. Create new otherwise. 
if (stat(fragmentSizesFilename_.c_str(), &st) == 0) // file existed
openExisting();
else
createNew();
}

我在init而不是构造函数中初始化的原因是,LinearScheme扩展了PartitionScheme(具有虚拟方法的超类)类,而另一个类则在递归使用构造函数的情况下这样做。

我有一个QuadTree类,它执行相同的初始化,因为每个QuadTree构造函数都是递归应用的。QuadTree类的init函数中的*this = QuadTree(bounds, maxSize)行工作正常。

然而,另一个子类(LinearScheme)*this = LinearScheme()中的这一行会导致Seg故障。

你知道为什么会发生这种事吗?

编辑同时替换行:

*this = LinearScheme()

这个:

*this;

或者将其整体移除可以消除Seg故障。。。为什么?

听起来factory method/builder/deferred construction的用法不正确。对于这些对象创建模式中的许多,构造对象的函数应该是一个静态方法,因为还不存在可操作的实例。在其他情况下,您可能会操作已构建的实例。在任何一种情况下,如果您实际上正在函数中构造类类型的对象,则应该使用new并最终返回它

如果您转而使用helper方法来帮助初始化,那么您不应该在方法本身中构造对象,而应该只在助手中初始化它的一部分。

工厂模式示例:

LinearScheme* LinearScheme::create(...all_your_args....) {
/* construct the thing we are building only if it 
*  pass any arguments into him that he can handle directly if you'd like
*/
LinearScheme *out = new LinearScheme(...);
/* do whatever else you have to do */
....
return out;
}

或者你似乎想要的helper

/* this time let's just do 'init' on your object */
void LinearScheme::init(....args....) {
/* possibly check if init has been done already */
if ( this->init ) return;
/* proceed to do your initialization stuff
* but don't construct the 'this' instance since it should already exist
*/
this->init = true; //so we don't init again if you don't need multiple init's
}

或者,您可以考虑亚历克斯提到的C++11中的委托构造函数方法。

然而,这两个都不是真正的问题。

它不起作用,因为你可能甚至没有一个有效的*this来表示尊重。这可能是因为您的使用,也可能是因为创建失败,可能是因为无限递归。

以下是关于该模式的维基百科链接:http://en.wikipedia.org/wiki/Factory_method_pattern

考虑到您所说的必须不断向父类和递归构造传递十几个参数,您可以考虑的一个建议是制作一个小的配置结构,通过引用传递,而不是所有离散参数。这样,您就不必在每次添加/删除另一个参数时不断调整每个签名。

另一个想法是将你的一个对象的构建与知道它们应该如何、在哪里和何时构建并插入你的层次结构的责任完全分开。如果不了解LinearSchme的实际使用方式以及接口是什么,很难说。

"…在另一个子类中(LinearScheme)*this = LinearScheme()">

"LinearScheme构造函数为空:LinearScheme::LinearScheme()">

如果*this是LinearMethod的子类,那么LinearMethod构造函数应该已经被调用了,而这一行是无用的。此外,它调用赋值运算符——它定义正确吗?

最好是依靠内置的构造对象的机制。如果您想避免代码重复,请使用C++11委派构造函数特性。它是专门为消除"init"方法而设计的。

尽管,"如果存在无限递归循环(例如,构造函数C1委托给另一个构造函数C2,C2也委托给C1),则行为是未定义的。">

因此,避免无限递归取决于您。在QuadTree中,您可以考虑在构造函数中创建指向QuadTreeNode的nullptr指针

相关文章: