Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: ошибка при линковке  (Прочитано 15430 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« : 18-06-2008 11:16 » 

Слов  нет, посему просто констатация факта. Скромно так...

Есть элемнтарный с++-проект без МФЦ. В нем 2 .cpp-файла (просто для читабельности - в одном основные функции, в другом все остальное) и 1 .h-файл.
В cpp-шках стоит:

Код:
#include "stdafx.h"
#include "alldbtypes.h"

А в alldbtypes.h - все include-файлы + все необходимые общие переменные.
Соответственно в лучших традициях все стоит в 

Код:
#ifndef ALLDBTYPES_IRI
#define ALLDBTYPES_IRI
#endif

При попытке собрать проект получаю - первый cpp-файл она собирает легко, а при попытке собрать второй:

readTables.obj : error LNK2005: "void * henv" (?henv@@3PAXA) already defined in my_odbc_test.obj

Бамс... У меня явно начался тормоз - я никак не пойму, почему??? Ведь ей же по-человечески сказали #ifndef!   Отлично
Я понимаю, что где-то что-то потеряла, но что-то не пойму что...
Записан

холоднокровней, Маня, Ви не на работе
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #1 : 18-06-2008 11:35 » 

Где у тебя #endif в заголовочном файле стоит? Должен в самом низу (конце) стоять.

Как это "при попытке собрать второй"? Ты их по отдельности собираешь?

с #pragma once пробовала?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #2 : 18-06-2008 11:40 » 

Malaja, думаю проще код показать, сразу ясно будет
Записан

С уважением Lapulya
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #3 : 18-06-2008 12:05 » 

Джон,

1) #endif стоит в самом конце.
2) Собираю я не по отдельности - я просто неверно выразилась.. Я хотела сказать, что в окошке, в котором отображается процесс компиляции, я вижу, что первый файл идет без проблем, а на втором мне рассказывают сказки про повторное объявление переменных.
3) с #pragma once еще не пробовала. Сейчас попробую.
Не спасло...

lapulja,

вот Код:

Код:

#include "stdafx.h"
#include "sql.h"
#include "sqlext.h"
#include <iostream.h>

#ifndef ALLDBTYPES_IRI
#define ALLDBTYPES_IRI

struct FieldInfo
{
    int             m_nColNumber;
    char            m_strFieldName[1024]; 
    SDWORD          m_nFieldType;
    int             m_nCurIndInArray;

    UCHAR           m_strCharVal[10000];
    WCHAR           m_strWCharVal[10000];
    long            m_nSLongVal;
    unsigned long   m_nULongVal;
    float           m_fFloatVal;
    double          m_fDoubleVal;
} ;


SQLHANDLE       hdbc = SQL_NULL_HDBC, henv = SQL_NULL_HDBC;

void readTable();
#endif

// my_odbc_test.cpp:

#include "stdafx.h"
#include "alldbtypes.h"

int connect ()
{
// ...
}

void disconnect ()
{
// ...
}
main()
{
   connect();
   readTable();
   disconnect();
}

//readTables.cpp:

#include "stdafx.h"
#include "alldbtypes.h"


void readTable()
{
//...
}

Записан

холоднокровней, Маня, Ви не на работе
McZim
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #4 : 18-06-2008 12:27 » 

зачем ты во всех трех файлах линкуеш (#include "stdafx.h") Не понял
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #5 : 18-06-2008 12:31 » 

McZim,

В проекте выставлены precompieled header files, т.е. если его не инклудировать, то при компиляции появляется ошибка:
fatal error C1010: unexpected end of file while looking for precompiled header directive

Убирать эту установку мне не с руки, т.к. это впоследствии не только мой проектик будет (его надо будет отдать другим как пример).
Записан

холоднокровней, Маня, Ви не на работе
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #6 : 18-06-2008 12:34 » 

McZim, это же VC++ Улыбаюсь
есть такой там stdafx.h precompiled header в него обычно кидаются всякие инклюды общие для всего проекта
Записан

Странно всё это....
McZim
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #7 : 18-06-2008 12:39 » 

может так?

Код:
#ifndef ALLDBTYPES_H_INCLUDED
#define ALLDBTYPES_H_INCLUDED
...
...
...
#endif // ALLDBTYPES_H_INCLUDED

хотя если это VC Улыбаюсь могу ошибаться.
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #8 : 18-06-2008 12:53 » 

McZim,

Смена имени константы ни к чему не привела - состояние больного стабильно тяжелое Ага
Записан

холоднокровней, Маня, Ви не на работе
Scorp__)
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 18-06-2008 13:09 » 

Malaja, а скажи, sql.h и sqlext.h точно защищены от повторного включения?
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #10 : 18-06-2008 13:13 » 

Scorp_,
дело в том, что в сообщении о повторной декларации переменных говорится только о моих  переменных, посему остальные хедеры я даже не проверяла, т.к. исхожу из того, что с этой стороны проблем быть не должно.
Записан

холоднокровней, Маня, Ви не на работе
McZim
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #11 : 18-06-2008 13:15 » 

Malaja, хм, а как на счет того что твои хедеры могут несколько раз подключать остальные хедеры и дело не в том что ты неправильно защитила свои хедеры а как раз в том что ты несколько раз подключила другие.
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #12 : 18-06-2008 13:38 » 

Ир, в h попробуй вот так сделать


Код:

#ifndef ALLDBTYPES_IRI
#define ALLDBTYPES_IRI

#include "sql.h"
#include "sqlext.h"
#include <iostream.h>

struct FieldInfo
{

....



УБЕРИ stdafx.h из хидера. Его только в срр инклудируй.
« Последнее редактирование: 18-06-2008 13:40 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Scorp__)
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 18-06-2008 13:48 » 

Да, действительно ошибка не там.
Malaja, посмотрел код повнимательнее и вспомнил где видел похожую ситуацию: в "Стандартах программирования на С++".
Рекомендация: "Не определяйте в заголовочном файле объекты со связыванием"
В общем, в хедере надо сделать объявление
extern SQLHANDLE hdbc;
extern SQLHANDLE henv;

А инициализацию и объявление вынести в один из файлов реализации. Защита не работает, у тебя же не каскадное включение, в каждый cpp файл включается свой экземпляр хедера, а макрос за пределами модуля конечно не работает.
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #14 : 18-06-2008 13:54 » 

Scorp_,
проверила - там все чисто (как минимум #ifndef есть)

по поводу стандартов - я как-то запуталась окончательно:
смотри, оба файла принадлежат одному проекту и используют одни и те же переменные. Далее, хедер должен включиться только как декларация типа "есть такая переменная в проекте". А сама переменная в разных местах устанавливается и используется.
Это же та же самая инстанция!
Или я неправа?

Джон,
попробовала сразу - не спасает...
Записан

холоднокровней, Маня, Ви не на работе
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #15 : 18-06-2008 14:04 » 

Scorp_,

сейчас попробовала с extern - работает! Спасибочки за подсказку!
Но почему без extern не работало, не пойму...
Записан

холоднокровней, Маня, Ви не на работе
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #16 : 18-06-2008 14:06 » 

ой, не дописала - пардон...
Когда я все организую без хедеров - тогда все понятно, т.к. другой файл должен знать о существовании переменных. Посему в первом файле они объявляются по-человечески, а во втором только как extern.
А тут...
Записан

холоднокровней, Маня, Ви не на работе
Scorp__)
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 18-06-2008 14:16 » 

Malaja, неа, один файл - это один модуль трансляции и компоновки, проект состоит из таких модулей. Хедер подключается к первому файлу, компоновщик видит переменную и определяет ее как объект. Потом компоновщик заканчивает с первым файлом и проделывает со вторым то же самое, но когда пытается определить объект для переменной, то обнаруживает что такой объект в проекте уже существует о чем тебе и сообщает.

То есть именно для объявления, что есть в проекте такая переменная нужно использовать рецепт с extern в хедере и реализацией в одном из cpp, этот объект будет виден по всему проекту.

Защита же нужна для другого случая: когда кто-то пишет свой класс или еще что-то и подключает в свой хедер твой. Затем кто-то третий, подключает сначала твой хедер, а потом тот второй (который уже включает твой). Вот здесь в пределах одного модуля защита срабатывает.

В общем, это разные инстанции ))

Дописываю пост )))

Когда очередь доходит до компоновщика, хедер уже прицеплен к cpp, и для компоновщика это одно целое. То есть, можно считать, что компоновщик все организует без хедеров сам )) (это чтобы не объяснять то, что интуитивно мне понятно, но словами выразить сложнее)

Может быть кто-то еще сможет подробнее объяснить работу компоновщика в этом случае и не запутаться в словах, а? 
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #18 : 18-06-2008 14:16 » 

Ирина, когда ты пишешь #include "bla-bla", то в текст твоего .cpp файла вставляется содержимое файла "bla-bla".  В результате и в первом, и во втором файле появляется строка с определениями глобальных переменных
Код:
SQLHANDLE       hdbc = SQL_NULL_HDBC, henv = SQL_NULL_HDBC;

Линковщик обругал тебя по делу - в двух объектных файлах определены символы с одинаковыми именами. При линковке это запрещено - всякий символ должен разрешаться однозначно.

Scort__),

никто ничего не цепляет/подключает. Препроцессор заменяет директиву #include "bla-bla" на ТЕКСТ файла bla-bla. В стандарте прямым текстом сказано (параграф 16.2):

Цитата
A preprocessing directive of the form
# include "q-char-sequence" new-line
causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner.

« Последнее редактирование: 18-06-2008 14:26 от npak » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #19 : 18-06-2008 14:29 » 

Все, ребята, огромное спасибо! Дошло!!!  Да-да
Это же не с++ со своими классами, это же с! И там таки каждый файл собирается по очереди, хоть они и сидят в одном проекте!
Извините за беспокойство  Краснею
Записан

холоднокровней, Маня, Ви не на работе
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 18-06-2008 14:37 » 

Ирина, в С++ у тебя все тоже самое - препроцессор и схема раздельной компиляции у них общие Улыбаюсь
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Scorp__)
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 18-06-2008 14:43 » 

npak, я знаю, что текст просто дописывается. Просто до компоновки происходит компиляция в объектный файл. Мне хотелось отразить и этот процесс в своей фразе.
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #22 : 18-06-2008 15:22 » 

npak, да, но в таком случае в срр будет вставлено


Код:

#ifndef ALLDBTYPES_IRI
#define ALLDBTYPES_IRI

...

SQLHANDLE       hdbc = SQL_NULL_HDBC, henv = SQL_NULL_HDBC;

...
#endif


Двух определений быть не должно. Хотя ошибка конечно в этом. Тему про extern мы уже где-то интенсивно обсуждали.

Ирина имела ввиду C#
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Scorp__)
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #23 : 18-06-2008 16:17 » 

Джон, но это будет вставлено в каждый cpp, и каждый cpp будет компилироваться и компоноваться отдельно от других, поэтому в каждом cpp макрос ALLDBTYPES_IRI не будет определен изначально.
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #24 : 18-06-2008 22:58 » 

Блиин, туплю по страшному. Scorp__), 100% прав.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #25 : 19-06-2008 08:23 » 

мда, когда руки набирают быстрее, чем думает голова, получаются нестыковочки
 Здесь была моя ладья...
Я имела в виду, что когда работаешь с классами, то такой ситуации просто не может быть, т.к. все функции-переменные принадлежат одному отдельно взятому классу. А как только начинаются глобальные переменные, так сразу же и начинается песенка про экстерн. Просто в нормальной жизни никаких глобальных переменных в нормальном с++-ном проекте при наличии классов не бывает.

Записан

холоднокровней, Маня, Ви не на работе
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #26 : 19-06-2008 08:41 » 

Malaja, еще как бывают!!!
Записан

С уважением Lapulya
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #27 : 19-06-2008 09:06 » 

в старых сплошь и рядом... И переделать невозможно, т.к. на эту работу никто не выделит время и деньги... Так что тут никуда не денешься.
А в новых это дело просто не пропускается еще на стадии дизайна. Т.е. есть жесткое условие - не применять под страхом смертной казни Ага А если программист не знает, как это обойти, должен спросить более опытных коллег - они подскажут.
Записан

холоднокровней, Маня, Ви не на работе
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #28 : 19-06-2008 09:28 » 

Ир, на самом деле это не так. Ага lapulya - прав. Загляни в любой свой MFC проект там ты всегда найдёшь нечто подобное:

extern CMyApp theApp;

Это глобальная инстанция твоей программы - объект, который должен быть создан. Ага

Конечно, если ты его не используешь в проге, то он хоть и будет без extern, но всё-равно глобальным.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #29 : 19-06-2008 09:56 » 

Джон,

ну так theApp - это же уже почти родное, т.е. мелкомягкое ;_)
А я имела в виду что-то введенное своими шаловливыми ручками Ага
Записан

холоднокровней, Маня, Ви не на работе
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines