【问题标题】:Symbols not found error when I appear to be including proper header当我似乎包含正确的标题时,找不到符号错误
【发布时间】:2016-01-28 01:17:19
【问题描述】:

我希望这个问题没有得到解答,很难阅读类似的问题,因为它们似乎都与 Xcode 中的 iOS 开发有关。我正在编写一个解析器,需要一个包含在我的语法(.y)和我的词法分析器(.l)文件中的标题。最初只包含标题而不定义函数会产生重复的符号错误。我读了一点 C++ 并尝试制作一个头文件和一个 cpp 文件。现在我收到了symbol(s) not found error。我想我只需要比我更了解 C++ 的人的帮助。此外,我正在慢慢地将这段代码从 C 转换为 C++,因此现在有一些非 C++ 的做事方式。

确切的错误是:

Undefined symbols for architecture x86_64:
  "symlook(char*)", referenced from:
      yylex() in lex.yy.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [outfile] Error 1

symtab.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NSYMS 20

struct symtab
{
    char *name;
    // ptr to C function to call if this entry is a fucntion name
    double (*funcptr)();
    double value;
};

extern symtab table[];

struct symtab *symlook(char *s);
void addfunc(char *name, double (*func)());

symtab.cpp

#include "symtab.h"

symtab table[NSYMS];

struct symtab *symlook(char *s) {
    char *p;
    struct symtab *sp;

    for(sp = table; sp < &table[NSYMS]; sp++) {
        /* is it already here? */
        if(sp->name && !strcmp(sp->name, s))
            return sp;
        if(!sp->name) { /* is it free */
            sp->name = strdup(s);
            return sp; 
        }
        /* otherwise continue to next */
    }
    fprintf(stderr, "%s\n", "Too many symbols");
    exit(1);    /* cannot continue */
} /* symlook */

void addfunc(char *name, double (*func)())
{
    struct symtab *sp = symlook(name);
    sp->funcptr = func;
}

简单.l

%{
#include "y.tab.h"
#include <math.h>
#include "symtab.h"
%}

%%

"if"    return IF;

"true"  return TRUE;
"false" return FALSE;

([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) {
        yylval.dval = atof(yytext); 
        return NUMBER; 
}

[ \t] ;  /* ignore whitespace */
[A-Za-z][A-Za-z0-9]*   { 
        yylval.symp = symlook(yytext);
        return NAME; 
}

"$"     return 0; /* logical EOF */

\n      |
.       return yytext[0];
%%

simple.y

%{
    #include "symtab.h"
    #include "ast.h"
    #include <string>
    #include <stdio.h>
    int yylex(void);
    void yyerror(char *);
%}

%union {
    double dval;
    int ival;
    struct symtab *symp;
}

%token <symp> NAME
%token <ival> INTEGER_LITERAL
%token <dval> NUMBER
%token IF TRUE FALSE WHILE
%left '-' '+'
%left '*' '/'
%nonassoc UMINUS

%type <dval> num_expression
%%

statement_list: statement '\n'
    |   statement_list statement '\n'
    ;

statement:  NAME '=' num_expression  { $1->value = $3; }
    |       num_expression           { fprintf(stderr, "= %g\n", $1); }
    |       if_expression
    |       bool_expression
    |       while_expression
    ;

num_expression: num_expression '+' num_expression   { $$ = $1 + $3; }
    |       num_expression '-' num_expression       { $$ = $1 - $3; }
    |       num_expression '*' num_expression       { $$ = $1 * $3; }
    |       num_expression '/' num_expression   
                { 
                    if($3 == 0.0)
                        yyerror("divide by zero");
                    else
                        $$ = $1 / $3;
                }
    |       '-' num_expression %prec UMINUS { $$ = -$2; }
    |       '(' num_expression ')'          { $$ = $2; }
    |       NUMBER                      
    |       NAME                            { $$ = $1->value; }
    |       NAME '(' num_expression ')'     { } //$$ = ($1->funcptr($3)); }
    ;
bool_expression: FALSE
    |            TRUE
    ;

if_expression:   IF '('  bool_expression ')' '{' statement '}'
    |            IF '(' ')' '{' '}'
    ;

while_expression: WHILE '('  bool_expression ')' '{' statement '}'
    |             WHILE '(' ')' '{' '}'
    ;

%% 

void yyerror(char *str)
{
    fprintf(stderr, "Error %s", str);
}


int main() {
    yyparse();
    return 0;
}

制作文件

CC=g++
outfile=simple
lexfile=simple
yaccfile=simple

outfile: compile
    ${CC} -o ${outfile}.out lex.yy.o y.tab.o -ll

compile: build
    ${CC} -c symtab.cpp
    ${CC} -c lex.yy.c y.tab.c -ll


build:
    yacc -d ${yaccfile}.y
    flex ${lexfile}.l

【问题讨论】:

  • 定义 !=未声明
  • 编译时,任何关于库-ll的参数都会被忽略(根本不应该存在)
  • 在编写编译步骤时(那些使用参数-c 对$(CC) 的调用,如果您包含了-o outputname 参数,那么问题的根源就很明显了. 一般情况下,使用-c 参数调用$(CC) 时最好只编译单个文件。build, compile` 目标不会生成同名文件,所以在早期makefile,需要是语句:.PHONY: build compile
  • 在定义宏时,(通常)宏只被评估一次。 = 导致宏在每次被引用时都被重新评估。使用:= 更好,因此宏只评估一次。

标签: c++ c header-files bison flex-lexer


【解决方案1】:

您的compile: build 步骤会生成一个文件symtab.o,您没有将其包含在链接行中。

【讨论】:

  • 感谢这项工作,我知道这很简单,但我发现的所有文档都非常冗长或神秘。
【解决方案2】:

这是很常见的错误。问题出在这里:

#include "y.tab.h"
#include <math.h>
#include "symtab.h"
  1. 在您的 Makefile 中,您需要首先执行 yacc's 命令,因为 yacc 正在生成您的 "y.tab.h" 文件。
  2. 你需要#include "y.tab.h"在所有其他包括!想想这个! y.tab.h 将包含来自 "symtab.h" 的内容,但 Lex 不知道那是什么,因为您在 "y.tab.h" 之后包含了 "symtab.h"

所以请记住: 您总是必须在所有其他包含之后包含 "y.tab.h" 以避免此错误!

【讨论】:

  • 这不会导致编译失败,而不是链接步骤吗?
猜你喜欢
  • 2021-12-16
  • 2016-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
  • 1970-01-01
  • 2012-09-03
相关资源
最近更新 更多