clang Linker fails if at least -O2 wasn't used

2019-07-21 15:38发布

问题:

I've an strage behaviour in a simple C code that I'm doing for educational purposes.

If I compile it with something lower than -O2 it breaks during link-edition with this output.

$ make
clang -Wall -march=native -pipe -c -g -D_DEBUG_ main.c
clang -Wall -march=native -pipe -c -g -D_DEBUG_ functions.c
clang -Wall -o main main.o functions.o 
Undefined symbols for architecture x86_64:
  "_getbit", referenced from:
      _getValueFromMatrix in functions.o
  "_setbit", referenced from:
      _populateMatrix in functions.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: *** [main] Error 1

I don't know if this helps but, here are the implementation of setbit(); and getbit();

inline void setbit(uint64_t *inteiro, unsigned char pos) {
    *(uint64_t*)inteiro |= (uint64_t)1 << pos;
}

inline bool getbit(uint64_t inteiro, unsigned char pos) {
    return (inteiro & ((uint64_t)1 << pos));
}

EDIT:

functions.h

#ifndef __FUNCTIONS_H__
#define __FUNCTIONS_H__

/* Funções para manipulação de bits */

inline void setbit(uint64_t *, unsigned char);

inline void clearbit(uint64_t *, unsigned char);

inline bool getbit(uint64_t, unsigned char);

inline unsigned char getbitChar(uint64_t, unsigned char);

char *uint64_t2bin(uint64_t, char *, int);

#endif

Includes in main.c

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

#include "errors.h"
#include "const.h"
#include "types.h"
#include "functions.h"

回答1:

inline only is the right thing to use, if there is a definition of the function in the .h file. It basically tells the compiler that it shouldn't produce a code for the function in every compilation unit (your .c files).

If there is no such definition in the .h file, as it seems here, just don't use inline at all, it just makes no sense.

If your worry is the efficiency of the other functions in the unit where you define your inline functions, you really don't need that. The compiler will inline any function that it has its hands on and where its criteria say that it is worth to do so.

If you really want to put the definitions to appear in the header file such that all units can see the definition, then use inline. In that case you'd have to include an "instantiation" of your function in just one unit, to ensure that the code is issued exactly once:

extern inline void setbit(uint64_t *, unsigned char);
extern inline void clearbit(uint64_t *, unsigned char);
extern inline bool getbit(uint64_t, unsigned char);
extern inline unsigned char getbitChar(uint64_t, unsigned char);


回答2:

The inline functions don't have any external definition, so when the compiler fails to inline them (which it won't do at -O0), the linker fails to find a definition, and an error results. The easiest fix is to change inline to static inline. Non-static inline is hard to use, confusing, and usually not useful.



标签: c clang break