如何使用GCC正确链接自定义C库?编译报错求助
编译自定义C库遇到的两个问题
问题背景
我自行实现了两个C库:
vector.h:仅包含宏定义,无需源文件,已用#pragma once防止头文件重复包含string库:包含string.h头文件和string.c源文件,依赖vector库,同样用#pragma once做重复包含防护
两个库均被main.c引用,编译过程中遇到以下两个问题:
- 直接执行编译命令:
gcc main.c -o build/main.exe,报错undefined reference tostringFunction,提示找不到string.h中声明的函数对应的string.c实现 - 分步骤编译再链接:
- 先编译目标文件:
gcc -c string/string.c -o build/obj/string.o、gcc -c main.c -o build/obj/main.o - 执行链接:
gcc -o build/main.exe build/obj/main.o build/obj/string.o,报错multiple definition ofvectorCreate_String,提示该函数在string.o和main.o中都有定义
- 先编译目标文件:
项目文件夹结构
PROJECT - string - string.c - string.h - vector - vector.h - main.c
代码文件内容
vector.h
#pragma once #include <stdlib.h> #define DEFINE_VECTOR(type) typedef struct { \ unsigned int size; \ size_t bytesize; \ type *data; \ } Vector_##type; \ Vector_##type *vectorCreate_##type(unsigned int initialSize, type *initialElements) { \ Vector_##type *v = (Vector_##type*)malloc(sizeof(Vector_##type)); \ v->size = initialSize; \ v->bytesize = initialSize * sizeof(type); \ v->data = (type*)malloc(v->bytesize); \ for (unsigned int i=0; i<initialSize; i++) v->data[i] = initialElements[i]; \ return v; \ } \ void vectorPush_##type(Vector_##type *v, type element) { \ v->size++; \ v->bytesize += sizeof(type); \ v->data = (type*)realloc(v->data, v->bytesize); \ v->data[v->size-1] = element; \ } \ void vectorFree_##type(Vector_##type *v) { \ free(v->data); \ free(v); \ } \ Vector_##type *vectorSlice_##type(Vector_##type *v, unsigned int start, unsigned int end) { \ Vector_##type *slice = (Vector_##type*)malloc(sizeof(Vector_##type)); \ slice->size = end - start; \ slice->bytesize = slice->size * sizeof(type); \ slice->data = (type*)malloc(slice->bytesize); \ for (unsigned int i=0; i<slice->size; i++) slice->data[i] = v->data[start + i]; \ return slice; \ } #define Vector(type) Vector_##type #define vectorCreate(type, initialSize, initialElements) vectorCreate_##type(initialSize, initialElements) #define vectorPush(type, vector, element) vectorPush_##type(vector, element) #define vectorFree(type, vector) vectorFree_##type(vector) #define vectorSlice(type, vector, start, end) vectorSlice_##type(vector, start, end)
string.h
#pragma once #include "../vector/vector.h" typedef struct { unsigned int length; char *str; } String; DEFINE_VECTOR(String); String *stringCreate(char *str); String *stringAppend(String *string, char *str); void stringFree(String *string); String *stringSlice(String *string, unsigned int start, unsigned int end); Vector(String) *stringSplit(String *string, char *delimiter);
string.c
#include "string.h" #include <stdio.h> #include <stdlib.h> #include <string.h> String *stringCreate(char *str) { String *string = malloc(sizeof(String)); string->length = strlen(str); string->str = malloc(string->length + 1); strcpy(string->str, str); return string; } String *stringAppend(String *string, char *str) { string->length += strlen(str); string->str = realloc(string->str, string->length + 1); strcat(string->str, str); return string; } void stringFree(String *string) { free(string->str); free(string); } String *stringSlice(String *string, unsigned int start, unsigned int end) { String *newString; newString->length = end - start; newString->str = malloc(newString->length + 1); for (unsigned int i=0; i<newString->length; i++) newString->str[i] = string->str[start + i]; newString->str[newString->length] = '\0'; return newString; } // not implemented yet Vector(String) *stringSplit(String *string, char *delimiter) { return NULL; }
main.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "./string/string.h" // stuff to test if everything is working properly int main(int argc, char *argv[]) { Vector(String) *strings = vectorCreate(String, 0, NULL); vectorPush(String, strings, *stringCreate("Hello")); vectorPush(String, strings, *stringCreate("World")); printf("%s %s\n", strings->data[0].str, strings->data[1].str); vectorFree(String, strings); return 0; }
问题原因及解决方法
问题1:undefined reference
原因:直接编译main.c时,gcc仅处理main.c文件,未将string.c的代码纳入编译流程,链接阶段无法找到string库函数的实现。
解决方法:编译时需将所有依赖的源文件一并传入:
gcc main.c string/string.c -o build/main.exe
问题2:multiple definition
原因:vector.h中的DEFINE_VECTOR宏会直接展开生成完整的函数实现代码,而非仅函数声明。string.h包含vector.h并调用DEFINE_VECTOR(String)后,string.c和main.c都会因包含string.h而生成vectorCreate_String等函数的实现,导致两个目标文件中存在重复的函数定义,链接时冲突。
解决方法:给宏生成的函数添加static关键字,将函数作用域限制在当前编译单元内,避免跨文件重复定义:
修改vector.h中的DEFINE_VECTOR宏,每个函数前加上static:
#define DEFINE_VECTOR(type) typedef struct { \ unsigned int size; \ size_t bytesize; \ type *data; \ } Vector_##type; \ static Vector_##type *vectorCreate_##type(unsigned int initialSize, type *initialElements) { \ Vector_##type *v = (Vector_##type*)malloc(sizeof(Vector_##type)); \ v->size = initialSize; \ v->bytesize = initialSize * sizeof(type); \ v->data = (type*)malloc(v->bytesize); \ for (unsigned int i=0; i<initialSize; i++) v->data[i] = initialElements[i]; \ return v; \ } \ static void vectorPush_##type(Vector_##type *v, type element) { \ v->size++; \ v->bytesize += sizeof(type); \ v->data = (type*)realloc(v->data, v->bytesize); \ v->data[v->size-1] = element; \ } \ static void vectorFree_##type(Vector_##type *v) { \ free(v->data); \ free(v); \ } \ static Vector_##type *vectorSlice_##type(Vector_##type *v, unsigned int start, unsigned int end) { \ Vector_##type *slice = (Vector_##type*)malloc(sizeof(Vector_##type)); \ slice->size = end - start; \ slice->bytesize = slice->size * sizeof(type); \ slice->data = (type*)malloc(slice->bytesize); \ for (unsigned int i=0; i<slice->size; i++) slice->data[i] = v->data[start + i]; \ return slice; \ }
额外修复:stringSlice函数的未初始化问题
stringSlice函数中String *newString;未初始化就直接赋值,会导致未定义行为,需修改为:
String *stringSlice(String *string, unsigned int start, unsigned int end) { String *newString = malloc(sizeof(String)); newString->length = end - start; newString->str = malloc(newString->length + 1); for (unsigned int i=0; i<newString->length; i++) newString->str[i] = string->str[start + i]; newString->str[newString->length] = '\0'; return newString; }
内容的提问来源于stack exchange,提问作者Konstei
相关产品推荐
相关产品推荐

