gcc编译时使用makefile链接错误

时间:2013-10-07 10:01:38

标签: c gcc linker makefile

(在继续之前,没有释放和编写代码中从未使用过的变量,
用于测试工具)

我写了像这样的代码和Makefile这样:

unread_two.h

#ifndef __UNREAD_TWO_H
#define __UNREAD_TWO_H

const int SIZEOF_INT = sizeof(int);
int addTwo();

unread_twomain.c

#include <stdio.h> 
#include <stdlib.h>
#include "unread_two.h"

int main(int argc, char *argv[])
{
    int *x;

    x = (int *)malloc(SIZEOF_INT);
    x = addTwo();
    free(x);

    return 0;
}

unread_two.c

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

int addTwo()
{
    int *y, *z, sum;
    y = (int *)malloc(SIZEOF_INT);
    z = (int *)malloc(SIZEOF_INT);

    *y = 3;
    sum = *y + *y;
    return sum;
}

生成文件

CC=gcc
CCFLAGS=-g

%.o: %.c
    $(CC) -c $< $(CCFLAGS)

all: unread_two
clobber: clean
    rm -f *~ \#`\# core

clean:
    rm -f unread_two *.o

unread_two: unread_twomain.o unread_two.o

unread_twomain.o: unread_two.h

unread_two.o: unread_two.h

当我把make all时,会显示以下消息:

unread_twomain.o:(.rodata+0x0): multiple definition of `SIZEOF_INT'
unread_two.o:(.rodata+0x0): first defined here
collect2: error: ld returned 1 exit status

我应该修理什么?

2 个答案:

答案 0 :(得分:4)

您不应该在标头中定义 SIZEOF_INT,否则当您在多个编译单元中包含此标头时,您将获得多个定义,如您所见。而是在标头中声明,并在源文件中定义

// unread_two.h

extern const int SIZEOF_INT;         // *declare* SIZEOF_INT


// unread_two.c

const int SIZEOF_INT = sizeof(int);  // *define* SIZEOF_INT


或者在这种特殊情况下,你可能有理由用“旧skool”的方式做一个宏:

// unread_two.h

#define SIZEOF_INT sizeof(int)

答案 1 :(得分:2)

你实际上有两个错误,你报告的错误和另一个更狡猾的错误。

您遇到错误的问题是,在包含头文件的所有源文件中定义了常量SIZEOF_INT。包含保护仅防止多个包含在同一源文件(或技术上的翻译单元)中说话),但不是你在多个来源中包含相同的文件。这意味着编译器将在SIZEOF_INTunread_twomain.o中创建unread_two.o的定义,然后链接器会抱怨。

解决方法是只在声明头文件中的常量,然后在单个源文件中定义


另一个问题是在main中你创建x作为指针,并为它分配内存(顺便说一下,你不应该对malloc的返回进行类型转换),并且然后将addTwo的结果分配给此指针。但是addTwo没有返回指针,它返回一个直值,所以你让指针x指向地址6,这不是你想要做的。当您尝试释放x指向的内存时,这将导致未定义的行为,最有可能导致崩溃。

在您的程序中,您不必使用指针。只需使用普通的非指针变量:

int addTwo()
{
    int y = 3;
    int sum = y + y;

    return sum;
}

int main(int argc, char *argv[])
{
    int x = addTwo();

    return 0;
}