我正在编写一个基于表达模板(元编程)的C ++库。
我有一个Matrix
类,我还实现了一个SubMatrix
类来提取矩阵的一部分。对于赋值具有不同操作数大小的情况,我已经为赋值=
运算符设置了异常处理,现在我正在为子矩阵索引的情况下的子矩阵提取设置异常处理与原始矩阵不匹配。我已经验证了作业=
的异常处理能够正常工作。
SubMatrix
提取的语法如下
B=SubMatrix(A,a,b,c,d);
具有以下Matlab等价物
B=A(a:b,c:d);
当我尝试
时Matrix<double> A_H(3,4);
Matrix<double> B_H(3,2);
try { B_H = SubMatrix(A_H,0,1,1,2); } catch(exception &e) { cout << e.what() << endl; return; }
捕获了SubMatrix
的正确异常,但程序随后立即中止。我已经验证通过向getch();
添加try-catch
来粗暴地冻结视频输出来捕获正确的异常,即
try { B_H = SubMatrix(A_H,0,1,1,2); } catch(exception &e) { cout << e.what() << endl; getch(); return; }
有人有解释吗? SubMatrix
的异常处理与作业=
的异常处理之间是否存在“干扰”?提前感谢您的帮助。
编辑 - 出现异常的功能
template<class T>
Expr<SubMatrixExpr<const T*,T>,T> SubMatrix(const Matrix<T>&v,const int a,const int b,const int c,const int d)
{ if((a >= 0) && (a < v.GetRows()) && (a <= b) && (b >= 0) && (b < v.GetRows()) &&
(c >= 0) && (c < v.GetColumns()) && (c <= d) && (d >= 0) && (d < v.GetColumns()))
{
typedef SubMatrixExpr<const T*,T> SExpr;
return Expr<SExpr,T>(SExpr(v.GetDataPointer(),v.GetRows(),v.GetColumns(),a,b,c,d),b-a+1,d-c+1);
} else { char* str0 = "************************************\n";
char* str1 = "* CPU SubMatrix indices must match *\n";
char* str2 = "Matrix size: ";
char* str3 = "SubMatrix indices (a,b,c,d): ";
char* catString = (char*) malloc(2*strlen(str0)+strlen(str1)+strlen(str2)+strlen(str3)+50*sizeof(char));
sprintf(catString, "%s%s%s\n%s%i x %i\n%s(%i,%i,%i,%i)\n",str0,str1,str0,str2,v.GetRows(),v.GetColumns(),str3,a,b,c,d);
throw GenericError(catString,__FILE__,__LINE__);
}
}
编辑 - 例外处理类
#define Error_msg_1 "Error in file"
#define Double_new_line "\n\n"
#define Error_msg_2 "on line"
class LibraryException: public std::exception
{
private:
const char *message_;
const char *file_;
int line_;
protected:
LibraryException(const char *message, const char* file, int line): message_(message), file_(file), line_(line) {}
public:
int get_line() const { return line_; }
const char* get_file() const { return file_; }
virtual const char* what() const throw()
{
char buf[20];
sprintf(buf, "%d", line_);
char* catString = (char*) malloc(strlen(Error_msg_1)+strlen(Double_new_line)+strlen(file_)+strlen(Double_new_line)+strlen(Error_msg_2)+strlen(buf)+strlen(message_));
sprintf(catString, "%s \n\n%s\n\n%s %s\n\n%s", Error_msg_1,file_,Error_msg_2,buf,message_);
return catString; }
};
class GenericError: public LibraryException
{
public:
GenericError(const char *message, const char* file, int line) :
LibraryException(message, file, line) {}
};
编辑 - MALLOC和VIRTUAL FUNCTIONS
从帖子What exactly is the problem with malloc() and virtual functions?开始,在虚拟函数中使用malloc
时出现问题。无论如何,我也试过使用new
,但问题仍然存在,我已经检查过我无法在virtual
函数中动态分配任何内容。此外,这个问题是“间歇性的”,有时会发生,有时则不会。最后,我用这样的静态分配解决了这个问题
virtual const char* what() const throw()
{
char buf[20];
sprintf(buf, "%d", line_);
char catString[2048];
sprintf(catString, "%s \n\n%s\n\n%s %s\n\n%s", Error_msg_1,file_,Error_msg_2,buf,message_);
return &catString[0]; }
};
答案 0 :(得分:1)
char* catString = (char*) malloc(strlen(Error_msg_1)+strlen(Double_new_line)+strlen(file_)+strlen(Double_new_line)+strlen(Error_msg_2)+strlen(buf)+strlen(message_));
此处没有足够的内存分配,因为除了所有字符串之外的格式字符串还包含空格\ ns和终止零。当Double_new_line被计为\ n \ n个空格而终点零仍然存在。
另外,为什么使用malloc
而非new
?甚至更好std::string
?由于我没有看到任何免费,这将导致内存泄漏。