(Makefile 错误)多个定义错误

Posted

技术标签:

【中文标题】(Makefile 错误)多个定义错误【英文标题】:(Makefile Error) Multiple definitions errors 【发布时间】:2020-04-18 22:12:29 【问题描述】:

基本上,我正在尝试为我目前正在处理的项目创建一个 makefile。 该错误表明我在两个不同的文件中定义了两次相同的函数。

错误在许多功能中反复出现,但为了简单起见,我只会放其中一个并尝试自己修复其他的,因为我会理解发生了什么。

这是 MakeFile 代码:

BIN=bin
INC=includes
OBJ=obj
LIB=lib
SRC=src

all : bin/main

$(OBJ)/utilidades.o: $(SRC)/utilidades.cpp $(INC)/utilidades.h
    g++ -c -o $(OBJ)/utilidades.o -I$(INC) $(SRC)/utilidades.cpp

$(OBJ)/main.o: $(SRC)/main.cpp $(INC)/utilidades.h 
    g++ -c -o $(OBJ)/main.o -I$(INC) $(SRC)/main.cpp

$(BIN)/main: $(OBJ)/main.o $(OBJ)/utilidades.o
    g++ -o $(BIN)/main $(OBJ)/main.o $(OBJ)/utilidades.o

cLean:
    echo "Cleaning Objects..."
    rm $(OBJ)/*.o

mrproper: clean
    rm 
    $(BIN)/main

这是 MakeFile 输出

g++ -o bin/main obj/main.o obj/utilidades.o
obj/utilidades.o: In function `mostrar(double*, int)':
utilidades.cpp:(.text+0x0): multiple definition of `mostrar(double*, int)'
obj/main.o:main.cpp:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
Makefile:16: recipe for target 'bin/main' failed
make: *** [bin/main] Error 1```

所以我一直在寻找那些在 main.cpp 中声明的函数:

#include <iostream>
#include "utilidades.cpp"

using namespace std;





int main()

    bool salir = false;
    char hold;
    int util1, util2, util3;
    double vtr_num1[100], vtr_num2[100], vtr_num3[200];
    double *ptr_vtr_num1, *ptr_vtr_num2, *ptr_vtr_num3;
    ptr_vtr_num1 = vtr_num1;
    ptr_vtr_num2 = vtr_num2;
    ptr_vtr_num3 = vtr_num3;

    cout << "       _               _      _       _____" << endl;
    cout << "  ___ (_) ___ _ __ ___(_) ___(_) ___ |___ /" << endl;
    cout << " / _  | |/ _ | '__/ __| |/ __| |/ _    |_  " << endl;
    cout << "|  __/| |  __| | | (__| | (__| | (_)  ___) |" << endl;
    cout << "|_____/ |____|_| |____|_| ___|_| ___/|____/" << endl;
    cout << "    |__/" << endl;


    while(!salir)

        cout << "\n\n\nCuantos numeros va a introducir en el primer vector: ";
        cin >> util1;
        cout << "\n Introduzcalos: ";

        for(int i=0; i<util1; i++)
            cin >> *(ptr_vtr_num1 + i);
        
        cout << "\n El vector 1 es: ";
        mostrar(ptr_vtr_num1, util1);

        cout << "\n Cuantos numeros va a introducir en el segundo vector: ";
        cin >> util2;

        cout << "\n Introduzcalos: ";
        for(int i=0; i<util2; i++)
            cin >> *(ptr_vtr_num2 + i);
        

        cout << "\n El vector 2 es: ";
        mostrar(ptr_vtr_num2, util2);
        cout << endl;

        mezclarUnico(util1, util2, util3, ptr_vtr_num1, ptr_vtr_num2, ptr_vtr_num3);


        cout << "Quiere salir? (s/n)";
        cin >> hold;
        if(hold == 's' || hold == 'S')
            salir = true;
        
    


    return 0;



但正如你所见,它们从未在 main.cpp 中声明,只在.ç 中声明

我声明它们的唯一位置是在我的实用程序.h 中(出于理解目的从 utilidades.h 翻译):

#include <iostream>
#ifndef UTILIDADES_H
#define UTILIDADES_H

void mostrar(double *ptr_vtr, int util);

int concatenar(int util1, int util2, double *ptr_vtr_num1, double *ptr_vtr_num2, int &util3, double *ptr_vtr_num3);

void eliminardobles(double *ptr_vtr_num, int &util);

void ordenador(double *ptr_vtr_num, int util);

void mezclarUnico(int util1, int util2, int util3, double * ptr_vtr_num1, double* ptr_vtr_num2, double* ptr_vtr_num3);

#endif

还有我的实用程序.cpp(从 utilidades.cpp 翻译过来):

#include <iostream>
#include "utilidades.h"

using namespace std;

/**
 * Muestra los valores de un vector
 * @param ptr_vtr el puntero al vector
 * @param util el tamanio del vector
 */
void mostrar(double *ptr_vtr, int util)
    for(int i=0; i < util; i++)        
        cout << *(ptr_vtr+i) << ", ";
    



/**
 * Concatena dos vectores en uno 3o.
 * @param util tamanio de los vectores.
 * \param ptr_vtr_num punteros a los vectores.
 */
int concatenar(int util1, int util2, double *ptr_vtr_num1, double *ptr_vtr_num2, int &util3, double *ptr_vtr_num3)

    for(int i=0; i<util1; i++)
        *(ptr_vtr_num3 + i) = *(ptr_vtr_num1 + i); 
    

    for(int i=0; i<util2; i++)
        *(ptr_vtr_num3 + util1 + i) = *(ptr_vtr_num2 + i);
    

    util3 = util1+util2;



/**
 * Elimina los dobles de un vector, suponiendo que estan ordenado
 * @param ptr_vtr_num El puntero que apunta al primer valor del vector a eliminar los dobles.
 * @param util El tamanyo del vector a ordenar, se pasa por referencia para guardar el tamanio despues de haber eliminado los dobles.
 */
void eliminardobles(double *ptr_vtr_num, int &util)
    for(int i=0; i<util-1; i++)
        if(*(ptr_vtr_num + i) == *(ptr_vtr_num + i + 1))
            for(int j=i; j<util-1; j++)
                *(ptr_vtr_num + j) = *(ptr_vtr_num + j + 1);
            
            util--;
            i--;                //Esta es la clave para que siga comparando por si acaso hay mas para que aunque se repita mas de dos veces las reconozca.
        
    


/**
 * Ordena los valores de un vector de doubles.
 * @param ptr_vtr_num El puntero al vector a ordenar
 * @param util Tamanio del vector
 */
void ordenador(double *ptr_vtr_num, int util)
    double aux;
    for(int j=0; j<util-1; j++)
        for(int i=0; i<util-1-j; i++)
            if(*(ptr_vtr_num + i) > *(ptr_vtr_num + i + 1))
                aux = *(ptr_vtr_num + i);
                *(ptr_vtr_num + i) = *(ptr_vtr_num + i + 1);
                *(ptr_vtr_num + i + 1) = aux;
            
        
    


/**
 * Aprovecha las funciones anteriores para mezclar dos vectores en uno tercero de forma qeu no se repitan valores
 * @param util Tamanios de los vectores
 * @param ptr_vtr_num Los punteros a los vectores
 */
void mezclarUnico(int util1, int util2, int util3, double * ptr_vtr_num1, double* ptr_vtr_num2, double* ptr_vtr_num3)

    cout << "\nConcatenando..." << endl;
        concatenar(util1, util2, ptr_vtr_num1, ptr_vtr_num2, util3, ptr_vtr_num3);



        cout << "\nOrdenando..." << endl;
        ordenador(ptr_vtr_num3, util3);

        cout << "\nEliminando dobles...\n\n------------------------------\n" << endl;
        eliminardobles(ptr_vtr_num3, util3);

        cout << "\nTam. resultante de mezclar ambos arrays: " << util3;
        cout << "\nEl vector final es: ";
        mostrar(ptr_vtr_num3, util3);
        cout << "\n\n";



那么为什么会出现这个错误,我该如何解决呢?

【问题讨论】:

#include "utilidades.cpp" 几乎总是错误的。您永远不应该直接包含 .cpp 文件 在指责你的makefile之前,试着手动构建你的项目(只有两个文件,不会花很长时间)。从问题中消除你的makefile将是迈向minimal reproducible example的一大步。 这能回答你的问题吗? Error with multiple definitions of function 【参考方案1】:

它们main.cpp 中声明。 #include 包含文本,因此utilities.cpp 的所有内容都有效地复制到main.cpp 中。请改用#include "utilities.h"

【讨论】:

对!所以我包括它是因为我输入了实用程序.cpp 而不是实用程序.h 有效地声明了两次!非常感谢!这对我来说是一个巨大的错误,我只是找不到它几个小时,并且有点急于完成它!非常感谢!顺便说一句,它告诉我我在 main.cpp 中 (.text+0x0) 声明它的原因可能是因为它是一个#include 文件而不是实际的代码行,所以它不能告诉我确切的行它是在 main.cpp 中声明的?再次感谢您! 部分。该错误将两个文件(main.o,从 main.cpp 编译,和实用程序.o,从 utilites.cpp 编译)链接在一起,这两个文件都包含mostrar 的定义。链接器不知道这些定义来自哪里,目标文件不存储这些数据(除了作为调试信息的一部分,如果有的话)。

以上是关于(Makefile 错误)多个定义错误的主要内容,如果未能解决你的问题,请参考以下文章

如何创建用于从子目录中的其他 Makefile 编译多个驱动程序的 Makeflow

Makefile文件的基本单元 —— 规则

makefie文件的基本说明和使用

makefie文件的基本说明和使用

使用 autotools 生成未定义的参考错误,而自定义 Makefile 工作正常

RealEvo IDE专家模式下应用工程MakeFile的修改