YACC - $1 的 strlen 是 0 尽管有字符串
YACC - strlen of $1 is 0 although string is there
我的程序出现奇怪的错误
我的YYSTYPE的结构是
%union
{
char *text;
node *n;
}
%token <text> NUMBER
语法规则是
P:
NUMBER
{
cout<<" : "<<<<endl;
int i = 0;
while([i])
{
cout<<"char : "<<[i++]<<endl;
}
$<n>$->left = $<n>$->right = NULL;
char *test1 = new char[strlen()];
strcpy(test1, );
cout<<"len : "<<strlen()<<"test1 : "<<test1<<endl;
char *lolz = strdup();
cout<<"dup : "<<((uint64_t)lolz)<<' '<<((int)lolz[1])<<" : dup"<<endl;
$<n>$->data = string();
cout<<"nd : "<<$<n>$->data<<endl;
print_tree($<n>$);
}
;
我可以打印 $1 的内容,但是当我执行 strlen($1) 时,它 returns 0 长度
这导致 strdup 和字符串初始化失败。
输出:
: 65301
char : 6
char : 5
char : 3
char : 0
char : 1
len : 0test1 :
dup : 26935504 0 : dup
Segmentation fault (core dumped)
我是不是漏掉了什么明显的东西?
当你执行:
$<n>$->left = $<n>$->right = NULL;
你认为 $<n>$
的值是多少?您是否已将其分配给 node
对象的地址?
为了节省你一些时间:你还没有分配它所以你可以把它当作一个未初始化的指针;取消引用未初始化的指针是未定义的行为,对应于您所看到的。
但这种分析并不十分准确。
bison 生成的解析器在执行操作之前将 $$
初始化为 </code>。在这种情况下,<code>
是一个联合,其 text
成员已分配给,因此使用 n
成员是(不同的)UB。结果是一样的,但在普通编译器中它更可预测:我假设 node
的 left
元素位于偏移量 0,因此上面的赋值会覆盖字符串的前 16 个字节零(如果您有 32 位体系结构,则为 8)。这可能是缓冲区溢出,但如果它没有出现段错误,最终结果是 </code> 的第一个字节为 0,因此 <code>strlen
的 return 值。 (当您尝试使用 data
元素时,它显然会出现段错误,大概是因为它不是初始化的 std::string
。使用零长度的 C 字符串对于 strdup
或 std::string
构造函数。)
道德:如果您不知道指针指向什么,请不要通过指针进行赋值。
顺便说一句,test1 的strcpy
是一个字节的缓冲区溢出。这次你好像逃过了一劫,但这是个坏习惯。
我的程序出现奇怪的错误
我的YYSTYPE的结构是
%union
{
char *text;
node *n;
}
%token <text> NUMBER
语法规则是
P:
NUMBER
{
cout<<" : "<<<<endl;
int i = 0;
while([i])
{
cout<<"char : "<<[i++]<<endl;
}
$<n>$->left = $<n>$->right = NULL;
char *test1 = new char[strlen()];
strcpy(test1, );
cout<<"len : "<<strlen()<<"test1 : "<<test1<<endl;
char *lolz = strdup();
cout<<"dup : "<<((uint64_t)lolz)<<' '<<((int)lolz[1])<<" : dup"<<endl;
$<n>$->data = string();
cout<<"nd : "<<$<n>$->data<<endl;
print_tree($<n>$);
}
;
我可以打印 $1 的内容,但是当我执行 strlen($1) 时,它 returns 0 长度 这导致 strdup 和字符串初始化失败。
输出:
: 65301
char : 6
char : 5
char : 3
char : 0
char : 1
len : 0test1 :
dup : 26935504 0 : dup
Segmentation fault (core dumped)
我是不是漏掉了什么明显的东西?
当你执行:
$<n>$->left = $<n>$->right = NULL;
你认为 $<n>$
的值是多少?您是否已将其分配给 node
对象的地址?
为了节省你一些时间:你还没有分配它所以你可以把它当作一个未初始化的指针;取消引用未初始化的指针是未定义的行为,对应于您所看到的。
但这种分析并不十分准确。
bison 生成的解析器在执行操作之前将 $$
初始化为 </code>。在这种情况下,<code>
是一个联合,其 text
成员已分配给,因此使用 n
成员是(不同的)UB。结果是一样的,但在普通编译器中它更可预测:我假设 node
的 left
元素位于偏移量 0,因此上面的赋值会覆盖字符串的前 16 个字节零(如果您有 32 位体系结构,则为 8)。这可能是缓冲区溢出,但如果它没有出现段错误,最终结果是 </code> 的第一个字节为 0,因此 <code>strlen
的 return 值。 (当您尝试使用 data
元素时,它显然会出现段错误,大概是因为它不是初始化的 std::string
。使用零长度的 C 字符串对于 strdup
或 std::string
构造函数。)
道德:如果您不知道指针指向什么,请不要通过指针进行赋值。
顺便说一句,test1 的strcpy
是一个字节的缓冲区溢出。这次你好像逃过了一劫,但这是个坏习惯。