有运行时错误的业力发生器有什么调试技巧
What debugging technique for a karma generator with runtime error
很难确定我的编程问题是什么,因为我真的看不出问题出在哪里。确实,我在 boost spirit karma 库的某处丢失了一个运行时错误。我想我在这里错过了调试技术。
我看到宏 BOOST_SPIRIT_DEBUG_NODE(S) 对解析器有很大帮助,虽然我找不到手册中对它的任何引用。对于生成器,这似乎不起作用,我(老实说)没有勇气(我应该吗?)深入研究这个库的代码以了解问题出在哪里。
我已经尝试在语法中单独生成我的三种类联合结构,没有任何问题。因此,我再次假设错误来自将 U 结构转换为 boost 变体(参见 ),但我没有证据。
对于那些可以通过简单的代码检查解决问题的人,这里是我的问题的最小示例:
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/karma.hpp>
#include <boost/variant/variant.hpp>
namespace ka = boost::spirit::karma;
typedef std::back_insert_iterator<std::string> iterator;
typedef enum {A, B, C } E;
typedef enum {FOO, BAR, POINTER } K;
struct U /* Union like */
{
K kind;
double foo;
E bar;
unsigned int * p;
};
class EName : public ka::symbols<E, std::string>
{
public:
EName()
{
add (A,"A") (B,"B") (C,"C");
}
};
typedef boost::variant<E, double, unsigned int *> UVariant;
namespace boost { namespace spirit { namespace traits {
template<>
struct transform_attribute<const U,UVariant,ka::domain>
{
typedef UVariant type;
static type pre(const U & u) {
switch (u.kind)
{
case FOO:
return type(u.foo);
case BAR:
return type(u.bar);
case POINTER:
return type(u.p);
}
return type(A);
}
};
}}}
class grm: public ka::grammar<iterator, U()>
{
public:
grm():grm::base_type(start)
{
start = ka::attr_cast<UVariant >(bar | foo | pointer);
bar = b;
foo = ka::double_;
pointer = ka::hex;
}
private:
ka::rule<iterator,U()> start;
ka::rule<iterator,double()> foo;
ka::rule<iterator,E()> bar;
ka::rule<iterator,unsigned int *()> pointer;
EName b;
};
int main(int argc, char * argv[])
{
grm g;
U u;
//unsigned int a;
u.kind = BAR;
//u.foo = 1.0;
u.bar = B;
//u.p = &a;
std::string generated;
std::back_insert_iterator<std::string> sink(generated);
ka::generate(sink,g,u);
std::cout << generated;
return 0;
}
更新: 编译器:Visual C++ Express 版本 11 和 12。调用堆栈停止在:
// If you are seeing a compilation error here stating that the
// third parameter can't be converted to a karma::reference
// then you are probably trying to use a rule or a grammar with
// an incompatible delimiter type.
if (f(sink, context, delim)) // <--- call stack stops here (last boost spirit reference)
我还发现 _SCL_SECURE_NO_WARNINGS 宏的定义隐藏了以下编译器警告:
warning C4996: 'std::_Copy_impl': Function call with parameters that
may be unsafe - this call relies on the caller to check that the
passed values are correct. To disable this warning, use
-D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
此警告涉及多个 boost-spirit 文件:
- spirit\home\karma\detail\output_iterator.hpp(242)
spirit\home\karma\detail\output_iterator.hpp(577)
spirit\home\karma\detail\output_iterator.hpp(574)
spirit\home\karma\detail\alternative_function.hpp(170)
spirit\home\karma\detail\alternative_function.hpp(162)
spirit\home\karma\operator\alternative.hpp(122)
spirit\home\karma\auxiliary\attr_cast.hpp(85)
spirit\home\karma\nonterminal\detail\generator_binder.hpp(43)
spirit\home\karma\nonterminal\detail\generator_binder.hpp(52)
spirit\home\karma\nonterminal\rule.hpp(193)
spirit\home\karma\nonterminal\rule.hpp(230)
我无法重现错误。
我也不能 "solve it" 一点代码检查。我 可以 但是做两件事:
我可以确认似乎没有为 Karma 实现调试宏
我可以大胆地说,也许 bar|foo|pointer
需要深度复制:
start = ka::attr_cast<UVariant >(boost::proto::deep_copy(bar | foo | pointer));
我尝试启用 UB-sanitizer 和 Address-sanitizer,但它们都没有报告任何问题。
UPDATE 事实上,我 可以 "solve" 它来自毕竟有点代码检查(和幸运的脑波):
事实上,valgrind 下的 运行 确实显示 a problem 并且确实在添加 deep_copy
时消失了。
我将添加一些关于我如何假设这些事情的参考资料:
总的来说:(Proto) 表达式模板中对临时对象的悬垂引用问题
- Assigning parsers to auto variables
特别是几年前在qi::attr_cast<>
看到的问题:
- 此评论来自 2014 年 1 月:Syntax tree empty nodes issue with Spirit Qi MiniC example
很难确定我的编程问题是什么,因为我真的看不出问题出在哪里。确实,我在 boost spirit karma 库的某处丢失了一个运行时错误。我想我在这里错过了调试技术。
我看到宏 BOOST_SPIRIT_DEBUG_NODE(S) 对解析器有很大帮助,虽然我找不到手册中对它的任何引用。对于生成器,这似乎不起作用,我(老实说)没有勇气(我应该吗?)深入研究这个库的代码以了解问题出在哪里。
我已经尝试在语法中单独生成我的三种类联合结构,没有任何问题。因此,我再次假设错误来自将 U 结构转换为 boost 变体(参见
对于那些可以通过简单的代码检查解决问题的人,这里是我的问题的最小示例:
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/karma.hpp>
#include <boost/variant/variant.hpp>
namespace ka = boost::spirit::karma;
typedef std::back_insert_iterator<std::string> iterator;
typedef enum {A, B, C } E;
typedef enum {FOO, BAR, POINTER } K;
struct U /* Union like */
{
K kind;
double foo;
E bar;
unsigned int * p;
};
class EName : public ka::symbols<E, std::string>
{
public:
EName()
{
add (A,"A") (B,"B") (C,"C");
}
};
typedef boost::variant<E, double, unsigned int *> UVariant;
namespace boost { namespace spirit { namespace traits {
template<>
struct transform_attribute<const U,UVariant,ka::domain>
{
typedef UVariant type;
static type pre(const U & u) {
switch (u.kind)
{
case FOO:
return type(u.foo);
case BAR:
return type(u.bar);
case POINTER:
return type(u.p);
}
return type(A);
}
};
}}}
class grm: public ka::grammar<iterator, U()>
{
public:
grm():grm::base_type(start)
{
start = ka::attr_cast<UVariant >(bar | foo | pointer);
bar = b;
foo = ka::double_;
pointer = ka::hex;
}
private:
ka::rule<iterator,U()> start;
ka::rule<iterator,double()> foo;
ka::rule<iterator,E()> bar;
ka::rule<iterator,unsigned int *()> pointer;
EName b;
};
int main(int argc, char * argv[])
{
grm g;
U u;
//unsigned int a;
u.kind = BAR;
//u.foo = 1.0;
u.bar = B;
//u.p = &a;
std::string generated;
std::back_insert_iterator<std::string> sink(generated);
ka::generate(sink,g,u);
std::cout << generated;
return 0;
}
更新: 编译器:Visual C++ Express 版本 11 和 12。调用堆栈停止在:
// If you are seeing a compilation error here stating that the
// third parameter can't be converted to a karma::reference
// then you are probably trying to use a rule or a grammar with
// an incompatible delimiter type.
if (f(sink, context, delim)) // <--- call stack stops here (last boost spirit reference)
我还发现 _SCL_SECURE_NO_WARNINGS 宏的定义隐藏了以下编译器警告:
warning C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
此警告涉及多个 boost-spirit 文件:
- spirit\home\karma\detail\output_iterator.hpp(242)
spirit\home\karma\detail\output_iterator.hpp(577)
spirit\home\karma\detail\output_iterator.hpp(574)
spirit\home\karma\detail\alternative_function.hpp(170)
spirit\home\karma\detail\alternative_function.hpp(162)
spirit\home\karma\operator\alternative.hpp(122)
spirit\home\karma\auxiliary\attr_cast.hpp(85)
spirit\home\karma\nonterminal\detail\generator_binder.hpp(43)
spirit\home\karma\nonterminal\detail\generator_binder.hpp(52)
spirit\home\karma\nonterminal\rule.hpp(193)
spirit\home\karma\nonterminal\rule.hpp(230)
我无法重现错误。
我也不能 "solve it" 一点代码检查。我 可以 但是做两件事:
我可以确认似乎没有为 Karma 实现调试宏
我可以大胆地说,也许
bar|foo|pointer
需要深度复制:start = ka::attr_cast<UVariant >(boost::proto::deep_copy(bar | foo | pointer));
我尝试启用 UB-sanitizer 和 Address-sanitizer,但它们都没有报告任何问题。
UPDATE 事实上,我 可以 "solve" 它来自毕竟有点代码检查(和幸运的脑波):
事实上,valgrind 下的 运行 确实显示 a problem 并且确实在添加 deep_copy
时消失了。
我将添加一些关于我如何假设这些事情的参考资料:
总的来说:(Proto) 表达式模板中对临时对象的悬垂引用问题
- Assigning parsers to auto variables
特别是几年前在
qi::attr_cast<>
看到的问题:- 此评论来自 2014 年 1 月:Syntax tree empty nodes issue with Spirit Qi MiniC example