Что означает «неопределенная ссылка на varName» в C? - PullRequest
15 голосов
/ 05 мая 2011

У меня есть 2 файла: a.c и b.c

В a.c Я посылаю сигнал функции, расположенной в b.c

signal(SIGUSR1,doSomething);

Поверх файла a.c у меня есть:

extern void doSomething (int    sig);

Однако, когда я компилирую, я получаю сообщение об ошибке:

/ tmp / ccCw9Yun.o: в функции main':<br> a.c:(.text+0xba): undefined reference to doSomething '
collect2: ld вернул 1 статус выхода

Включены следующие заголовки:

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

Как мне это исправить?

Ответы [ 6 ]

17 голосов
/ 05 мая 2011

Вам необходимо связать и a.o, и b.o:

gcc -o program a.c b.c

Если у вас есть main() в каждом файле, вы не можете связать их вместе.

Однако ваш файл a.c содержит ссылку на doSomething() и предполагает связь с исходным файлом, который определяет doSomething() и не определяет функции, определенной в a.c (например, main() ).

Вы не можете вызвать функцию в процессе B из процесса A. Вы не можете отправить сигнал функции; вы отправляете сигналы процессам, используя системный вызов kill().

Функция signal() указывает, какая функция в вашем текущем процессе (программе) будет обрабатывать сигнал, когда ваш процесс получает сигнал.

У вас есть серьезная работа, чтобы понять, как это будет работать - как ProgramA узнает, на какой идентификатор процесса отправить сигнал. Код в b.c должен вызвать signal() с dosomething в качестве обработчика сигнала. Код в a.c просто отправит сигнал другому процессу.

10 голосов
/ 05 мая 2011

Это очень плохой стиль для определения внешних интерфейсов в файлах .c. ,

Вы должны сделать это

хиджры

    extern void doSomething (int    sig);

a.c

    void doSomething (int    sig)
    {
       ... do stuff 
    }

b.c

#include "a.h"
.....
signal(SIGNAL, doSomething); 

.

4 голосов
/ 05 мая 2011

Первоначальной реакцией на это было бы спросить и убедиться, что два объектных файла связаны друг с другом.Это делается на этапе компиляции путем компиляции обоих файлов одновременно:

gcc -o programName a.c b.c

Или, если вы хотите скомпилировать отдельно, это будет:

gcc -c a.c
gcc -c b.c
gcc -o programName a.o b.o
3 голосов
/ 05 мая 2011

Вам нужно скомпилировать, а затем связать объектные файлы, как это:

gcc -c a.c  
gcc -c b.c  
gcc a.o b.o -o prog  
3 голосов
/ 05 мая 2011

Вы получаете ошибку компоновщика, поэтому ваш extern работает (компилятор скомпилировал a.c без проблем), но когда он в конце связал объектные файлы вместе, он не смог разрешить ваш extern - void doSomething(int); фактически нигде не был найден. Ты испортил экстерьер? Убедитесь, что на самом деле есть doSomething, определенный в b.c, который принимает int и возвращает void, и убедитесь, что вы не забыли включить b.c в свой список файлов (т.е. вы делаете что-то вроде gcc a.c b.c не только gcc a.c)

1 голос
/ 17 декабря 2012

убедитесь, что ваша функция doSomething не является статичной.

...