DebugUtil.h
#ifndef DEBUG_UTIL_H
#define DEBUG_UTIL_H
#include <windows.h>
int DebugMessage(const char* message)
{
const int MAX_CHARS = 1023;
static char s_buffer[MAX_CHARS+1];
return 0;
}
#endif
When I try to run this I get this error:
Terrain.obj : error LNK2005: «int
__cdecl DebugMessage(char const *)» (?DebugMessage@@YAHPBD@Z) already
defined in Loodus.objRenderer.obj : error LNK2005: «int
__cdecl DebugMessage(char const *)» (?DebugMessage@@YAHPBD@Z) already
defined in Loodus.objtest.obj : error LNK2005: «int __cdecl
DebugMessage(char const *)»
(?DebugMessage@@YAHPBD@Z) already
defined in Loodus.objC:UsersTiagoDesktopLoodus
EngineDebugLoodus Engine.exe : fatal
error LNK1169: one or more multiply
defined symbols found
But why does this happen? I have #ifndef #define and #endif in the header so multiple definitions shouldn’t happen
asked Jun 24, 2011 at 15:14
Tiago CostaTiago Costa
4,10112 gold badges34 silver badges54 bronze badges
2
Put the definition (body) in a cpp file and leave only the declaration in a h file. Include guards operate only within one translation unit (aka source file), not across all your program.
The One Definition Rule of the C++ standard states that there shall appear exactly one definition of each non-inline function that is used in the program. So, another alternative would be to make your function inline.
answered Jun 24, 2011 at 15:16
Armen TsirunyanArmen Tsirunyan
128k57 gold badges323 silver badges432 bronze badges
4
Make the function inline or declare the function in a header file and define it in a cpp file.
inline int DebugMessage(const char* message)
{
const int MAX_CHARS = 1023;
static char s_buffer[MAX_CHARS+1];
return 0;
}
EDIT:
As a comment by Tomalak Geret’kal suggests, it’s better to use my latter suggestions than my former and move the function’s declaration to a cpp file.
answered Jun 24, 2011 at 15:17
3
(Assuming the posted code is a header, included from multiple .cpp files)
Header guards do not protect you from link-time multiple definitions. Regardless that you have ensured the header will only appear once per Translation Unit, if you have more than one Translation Unit then that’s still multiple definitions.
Write definitions in source files, and only declarations in headers.
The only exceptions are inline functions, functions defined within a class definition (though this is not recommended!) and function templates.
answered Jun 24, 2011 at 15:19
3
This function is included into every translation unit and as a result you get multiple definitions of it — each .obj file contains its own copy. When it’s time to link them all together the linker rightfully shows the above error.
You can do a few things:
- Move the definition to a .cpp file and keep only the declaration in the header.
- Use an anonymous namespace around the function in your header file (but realize it’s a hack — you will still have multiple definitions, just no name collision).
- Mark it as inline (although it might not always work — only if the compiler actually chooses to inline it). That’s also a hack for the same reason as above.
answered Jun 24, 2011 at 15:18
Assaf LavieAssaf Lavie
71k33 gold badges144 silver badges201 bronze badges
That only prevents multiple inclusions in the same source file; multiple source files #includeing it will still generate multiple definitions of DebugMessage(). In general, you should either not place functions in header files at all or make them static (and usually inline, since otherwise it doesn’t usually make sense to have multiple static definitions of the same function).
answered Jun 24, 2011 at 15:18
geekosaurgeekosaur
58.1k11 gold badges120 silver badges112 bronze badges
100% Certain you correctly included Guards but still getting redefinition error?
For Visual Studio:
I was really frustrated because I was correctly included guards,
only to find out the problem was visual studio. If you have added the file
to your project, the compiler will add the file twice even if you have
include guards around your implementation file and header file.
If you don’t use visual studio exclusively, and say… use code::blocks sometimes, you might want to only #include the file when you detect the absence of the visual studio environment.
DebugUtil.h :
----------------------
#ifndef _WIN32
#include "DebugUtil.c"
#endif
----------------------
If you are okay with including stdio.h,
you can be a little less hackish about it:
DebugUtil.h :
----------------------
#include <stdio.h>
#ifdef _MSC_VER
#include "DebugUtil.c"
#endif
----------------------
Reference:
Predefined Macros, Visual Studio:
https://msdn.microsoft.com/en-us/library/b0084kay.aspx
aldoWan
931 silver badge6 bronze badges
answered Sep 9, 2017 at 16:47
KANJICODERKANJICODER
3,47729 silver badges16 bronze badges
Move the definition to a .cpp file.
answered Jun 24, 2011 at 15:17
MGZeroMGZero
5,6945 gold badges28 silver badges46 bronze badges
Declare your functions in C++ files. Since you defined your function in the header file, and that header file is included from multiple source files, it gets defined for each source file that includes it. That’s why it’s reported as being defined in multiple places.
Alternatively, you could make it inline so that the code is inserted wherever it’s used instead of being defined as a separate function each time.
answered Jun 24, 2011 at 15:17
Jonathan WoodJonathan Wood
64.2k69 gold badges258 silver badges442 bronze badges
It looks like you are including DebugUtil.h in more than one translation unit, then linking those objects together. However, DebugUtil.h provides a definition for the DebugMessage function, so that definition exists in all of the translation units that incorporated the header. As a result, when you link the objects, the linker rightly complains that the symbol is multiply defined.
Change DebugUtil.h so that it declares DebugMessage via a prototype, but does not provide a definition, and place the definition of DebugMessage in a .c file which you will compile and link with your other objects.
answered Jun 24, 2011 at 15:17
acmacm
12k5 gold badges36 silver badges66 bronze badges
Hi ULARbro,
Welcome to MSDN forum.
>> Fatal error
LNK1169
## This error is preceded by error
LNK2005. Generally, this error means you have broken the one definition rule, which allows only one definition for any used template, function, type, or object in a given object file, and only one definition across the entire executable for externally visible
objects or functions.
Do you meet this error when you are running test project? And does your project build/debug well without any error?
According to the official document, You could refer to below possible causes and for
solutions please refer to this link
Possible causes and solutions.
(1) Check if one of your header file defines a variable and maybe include this header file in more than one source file in your project.
(2) This error can occur when a header file defines a function that isn’t inline. If you include this header file in more than one source file, you get multiple definitions of the function in the executable.
(3) This error can also occur if you define member functions outside the class declaration in a header file.
(4) This error can occur if you link more than one version of the standard library or CRT.
(5) This error can occur if you mix use of static and dynamic libraries when you use the /clr option
(6) This error can occur if the symbol is a packaged function (created by compiling with /Gy)
and it was included in more than one file, but was changed between compilations.
(7)
This error can occur if the symbol is defined differently in two member objects in different libraries, and both member objects are used. One way to fix this issue when the libraries are statically linked is to use the member object from only one library,
and include that library first on the linker command line.
(8)
This error can occur if an extern const variable is defined twice, and has a different value in each definition.
(9) This error can occur if you use uuid.lib in combination with other .lib files that define GUIDs (for example, oledb.lib and adsiid.lib).
There are some similar issues and maybe helpful.
LNK1169 and LNK2005 Errors.
Fatal error LNK1169: one or more multiply defined symbols found in game programming.
Fatal error LNK1169: one or more multiply defined symbols found.
Hope all above could help you.
Best Regards,
Tianyu
MSDN Community Support
Please remember to click «Mark as Answer» the responses that resolved your issue, and to click «Unmark as Answer» if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to
MSDN Support, feel free to contact MSDNFSF@microsoft.com.
-
Proposed as answer by
Friday, December 13, 2019 9:31 AM
|
Асурус 2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
||||||||||||||||||||||||
|
1 |
||||||||||||||||||||||||
|
05.07.2013, 09:51. Показов 4479. Ответов 16 Метки нет (Все метки)
Доброго всем времени суток! Никак не могу разобраться в чём дело… Помогите пожалуйста!
Get_String_Getche.h
Very_Long_Number.h
Get_String_Getche.cpp
Very_Long_Number.cpp
Выдаёт вот это: fatal error LNK1169: one or more multiply defined symbols found Добавлено через 18 минут
__________________
0 |
|
2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
|
|
08.07.2013, 11:17 [ТС] |
2 |
|
Help please! Добавлено через 22 часа 21 минуту Добавлено через 1 час 23 минуты Добавлено через 10 часов 12 минут
0 |
|
alsav22 5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
||||
|
09.07.2013, 06:30 |
3 |
|||
|
Это из-за:
в Very_Long_Number.h. Он подключается в двух файлах (main() и Very_Long_Number.cpp), отсюда множетсвенное определение.
1 |
|
2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
|
|
09.07.2013, 06:43 [ТС] |
4 |
|
Спасибо… кажется разобрался.
0 |
|
alsav22 5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
||||
|
09.07.2013, 06:53 |
5 |
|||
|
Только как от этого избавиться (в студии) я не занаю, кроме как убрать из файлов все объявленя/определения SZ и прописать в Get_String_Getche.h:
Добавлено через 2 минуты
0 |
|
Асурус 2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
||||
|
09.07.2013, 07:06 [ТС] |
6 |
|||
|
Я перенёс
в «stdafx.h» и проблема решена.
0 |
|
Tulosba |
|
09.07.2013, 07:33
|
|
Не по теме:
И ещё, рекомендуется using namespace std; помещать, в файле, после всех инклудов. Рекомендуется не использовать данную запись в принципе.
0 |
|
alsav22 |
|
09.07.2013, 07:44
|
|
Не по теме:
Рекомендуется не использовать данную запись в принципе. В заголовочных файлах.
0 |
|
alsav22 |
|
09.07.2013, 07:54
|
|
0 |
|
alsav22 5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
||||
|
09.07.2013, 07:59 |
10 |
|||
|
Я перенёс
в «stdafx.h» и проблема решена. Откуда что перенесли? Не пойму, как это может помочь, если stdafx.h тоже подключен к нескольким .cpp?
0 |
|
Асурус 2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
||||
|
09.07.2013, 08:04 [ТС] |
11 |
|||
— кажется эта директива служит защитой от множественного включения
0 |
|
5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
|
|
09.07.2013, 08:06 |
12 |
|
А что конкретно перенесли? Откуда?
0 |
|
Асурус 2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
||||
|
09.07.2013, 08:10 [ТС] |
13 |
|||
— удалил из файла с main(), и из «Very_Long_Number.cpp», и записал в «stdafx.h»
0 |
|
5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
|
|
09.07.2013, 08:16 |
14 |
|
У меня ошибка остаётся. Не понятно, почему у вас нет. Весь проект может выложить?
0 |
|
Асурус 2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
||||||||||||||||||||||||
|
09.07.2013, 08:27 [ТС] |
15 |
|||||||||||||||||||||||
|
У меня там много и других ошибок… вот проект:
stdafx.h
Very_Long_Number.h
Class_Very_Long_Number.cpp
Get_String_Getche.cpp
Very_Long_Number.cpp
0 |
|
5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
|
|
09.07.2013, 08:42 |
16 |
|
вот проект: Я имел ввиду файлы студии. Добавлено через 54 секунды
У меня там много и других ошибок… Может до этой просто не доходит? Добавлено через 6 минут
0 |
|
2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
|
|
09.07.2013, 08:58 [ТС] |
17 |
|
Не, теперь всё в норме, я закоментировал вызовы функций с ошибками, всё выполняется. Добавлено через 1 минуту Добавлено через 7 минут
0 |
Содержание
- Fatal error lnk1169 one or more multiply defined symbols found
- Asked by:
- Question
- All replies
- Fatal error lnk1169 one or more multiply defined symbols found
- Asked by:
- Question
- All replies
- Fatal error lnk1169 one or more multiply defined symbols found
- Fatal error lnk1169 one or more multiply defined symbols found
- Answered by:
- Question
- Fatal error lnk1169 one or more multiply defined symbols found
Fatal error lnk1169 one or more multiply defined symbols found
This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.
Asked by:
Question
fatal error LNK1169: one or more multiply defined symbols found
How can i fix this error?
Welcome to MSDN forum.
>> Fatal error LNK1169
## This error is preceded by error LNK2005. Generally, this error means you have broken the one definition rule, which allows only one definition for any used template, function, type, or object in a given object file, and only one definition across the entire executable for externally visible objects or functions.
Do you meet this error when you are running test project? And does your project build/debug well without any error?
According to the official document, You could refer to below possible causes and for solutions please refer to this link Possible causes and solutions.
(1) Check if one of your header file defines a variable and maybe include this header file in more than one source file in your project.
(2) This error can occur when a header file defines a function that isn’t inline. If you include this header file in more than one source file, you get multiple definitions of the function in the executable.
(3) This error can also occur if you define member functions outside the class declaration in a header file.
(4) This error can occur if you link more than one version of the standard library or CRT.
(5) This error can occur if you mix use of static and dynamic libraries when you use the /clr option
(6) This error can occur if the symbol is a packaged function (created by compiling with /Gy ) and it was included in more than one file, but was changed between compilations.
(7) This error can occur if the symbol is defined differently in two member objects in different libraries, and both member objects are used. One way to fix this issue when the libraries are statically linked is to use the member object from only one library, and include that library first on the linker command line.
(8) This error can occur if an extern const variable is defined twice, and has a different value in each definition.
(9) This error can occur if you use uuid.lib in combination with other .lib files that define GUIDs (for example, oledb.lib and adsiid.lib).
There are some similar issues and maybe helpful.
Источник
Fatal error lnk1169 one or more multiply defined symbols found
This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.
Asked by:
Question
fatal error LNK1169: one or more multiply defined symbols found
How can i fix this error?
Welcome to MSDN forum.
>> Fatal error LNK1169
## This error is preceded by error LNK2005. Generally, this error means you have broken the one definition rule, which allows only one definition for any used template, function, type, or object in a given object file, and only one definition across the entire executable for externally visible objects or functions.
Do you meet this error when you are running test project? And does your project build/debug well without any error?
According to the official document, You could refer to below possible causes and for solutions please refer to this link Possible causes and solutions.
(1) Check if one of your header file defines a variable and maybe include this header file in more than one source file in your project.
(2) This error can occur when a header file defines a function that isn’t inline. If you include this header file in more than one source file, you get multiple definitions of the function in the executable.
(3) This error can also occur if you define member functions outside the class declaration in a header file.
(4) This error can occur if you link more than one version of the standard library or CRT.
(5) This error can occur if you mix use of static and dynamic libraries when you use the /clr option
(6) This error can occur if the symbol is a packaged function (created by compiling with /Gy ) and it was included in more than one file, but was changed between compilations.
(7) This error can occur if the symbol is defined differently in two member objects in different libraries, and both member objects are used. One way to fix this issue when the libraries are statically linked is to use the member object from only one library, and include that library first on the linker command line.
(8) This error can occur if an extern const variable is defined twice, and has a different value in each definition.
(9) This error can occur if you use uuid.lib in combination with other .lib files that define GUIDs (for example, oledb.lib and adsiid.lib).
There are some similar issues and maybe helpful.
Источник
Fatal error lnk1169 one or more multiply defined symbols found
Write your question here. Hi, it is me again. I am getting this error and cannot figure out what I am doing wrong. It is in visual studios 2013 again BTW.
[#include «stdafx.h» // Precompiled header
#include «iostream» // Input and output stream
using namespace std; // Meaning you don’t have to put std:: before cout Last edited on
can you use code tags please?
for example, you prototype:
int squareIntegers();
but you call it like this:
squareIntegers(22)
you also do not need prototype declarations if you’re implementing them before you call them.
i.e. delete these:
why are you doing calculations and then return zero?
edit:
you also do not need this either:
are wrong, and not even needed.
I did it because I cannot return both answer1 and answer2 twice.
You need to read that link i pasted on functions.
So, I read it but and why are
[int squareIntegers(); // Function Prototype
double squareDouble();
float squareFloat();], wrong. They are function prototypes.
Also, I get an error saying to include «stdafx.h» if I don’t include it.
Also, for squareIntegers(22), I used this in my last program, and it worked fine. I have no idea what else could be the issue.
They are function prototypes.
Yes they are, but they don’t match your functions!
This prototype:
You’re telling the compiler about a different function. This one takes an integer and returns an integer.
This issue becomes apparent when you move your functions implementations below your main function:
(10): error C2660: ‘squareIntegers’ : function does not take 1 arguments
(11): error C2660: ‘squareDouble’ : function does not take 1 arguments
(12): error C2660: ‘squareFloat’ : function does not take 2 arguments
Because your prototypes should be:
Okay, thanks for that, but I still have this error: «fatal error LNK1169: one or more multiply defined symbols found.»
Does this mean in my squareFloat function, I need to make a struct, return the struct name? Will that get rid of this error?
Источник
Fatal error lnk1169 one or more multiply defined symbols found
Answered by:
Question
I’ve read other posts about this and usually it’s caused by accidently adding two or more copies of the same source code to the project.
I have three source code files and I can’t identify which symbol is ‘multiply defined’. This link error only occured when I started building the release version, it was fine on debug, so I have no idea when the problem started.
Here is the full error report:
—— Rebuild All started: Project: solver, Configuration: Release Win32 ——
Deleting intermediate and output files for project ‘solver’, configuration ‘Release|Win32’
.solver.cpp(240) : warning C4244: ‘=’ : conversion from ‘double’ to ‘float’, possible loss of data
.solver.cpp(269) : warning C4305: ‘=’ : truncation from ‘double’ to ‘float’
.solver.cpp(271) : warning C4244: ‘=’ : conversion from ‘double’ to ‘float’, possible loss of data
warning C4727: PCH named c:documents and settingsusermy documentsvisual studio 2005projectssolversolverreleasesolver.pch with same timestamp found in c:Documents and SettingsuserMy DocumentsVisual Studio 2005ProjectssolversolverReleasestdafx.obj and c:Documents and SettingsuserMy DocumentsVisual Studio 2005ProjectssolversolverReleasesolver.obj. Using first PCH.
stdafx.obj : error LNK2005: ___@@_PchSym_@00@UwlxfnvmghLzmwLhvggrmthUfhviUnbLwlxfnvmghUerhfzoLhgfwrlLCAAFUkilqvxghUhloeviUhloeviUivovzhvUhgwzucOlyq@ already defined in solver.obj
C:Documents and SettingsuserMy DocumentsVisual Studio 2005ProjectssolverReleasesolver.exe : fatal error LNK1169: one or more multiply defined symbols found
Build log was saved at «file://c:Documents and SettingsuserMy DocumentsVisual Studio 2005ProjectssolversolverReleaseBuildLog.htm»
solver — 2 error(s), 3 warning(s)
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
Источник
Fatal error lnk1169 one or more multiply defined symbols found
При компиляции происходят ошибки:
1 — error LNK2005: _assetType already defined in customer.obj
2 — fatal error LNK1169: one or more multiply defined symbols found
Погуглив я понял, что компилятор вставляет 2 раз вот это
но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
Почему тогда происходит ошибка и как ее исправить?
Большое спасибо.
| |
От: | Caracrist | https://1pwd.org/ |
| Дата: | 07.06.09 12:10 | ||
| Оценка: | -2 |
| |
От: | Caracrist | https://1pwd.org/ |
| Дата: | 07.06.09 12:26 | ||
| Оценка: | +1 |
Здравствуйте, Caracrist, Вы писали:
C>this ?
C>
это я прогнал
| |
От: | andrey.desman |
| Дата: | 07.06.09 12:45 | |
| Оценка: |
| |
От: | Alexey F |
| Дата: | 07.06.09 12:51 | |
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>При компиляции происходят ошибки:
TA>1 — error LNK2005: _assetType already defined in customer.obj
TA>2 — fatal error LNK1169: one or more multiply defined symbols found
TA>Погуглив я понял, что компилятор вставляет 2 раз вот это
TA>
В дополнение к данным выше ответам:
Так тоже будет работать (подразумевается внутреннее связывание).
TA>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
Верно. По одному разу в каждый файл, который подключил customer.h.
P.S. Если нет желания делать массив константным или внутренним для каждой единицы трансляции, то только так:
в заголовке его объявляем с extern, а определяем в отдельном .c/.cpp файле
| |
От: | TheAteist |
| Дата: | 07.06.09 20:01 | |
| Оценка: |
| |
От: | TheAteist |
| Дата: | 07.06.09 20:02 | |
| Оценка: |
| |
От: | Kirikaza | kirikaza.ru |
| Дата: | 07.06.09 20:35 | ||
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
TA>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
#include «x.h» лучше рассматривать как «вставить в этом месте содержимое файла x.h».
Пусть есть файл x.h:
Если файл x.h вставлен дважды в некий C-файл
то получается вот так:
При этом первый #ifndef сработает, т.к. X_H ещё не определена, и определит X_H. А второй #ifndef не сработает, т.к. X_H уже определена.
Когда происходит компиляция, препроцессор берёт C-файл выполняет вот эту подстановку и оставляет код внутри первого #if и выкидывает внутри второго. Затем полученный код отдаётся компилятору, который компилирует и получает объектный файл. Затем берётся второй C-файл и для него независимо от первого C-файла процедура повторяется заново (т.е. в самом начале обработки препроцессором второго C-файла X_H никем не была определена). Когда все объектные файлы получены, они все линкуются (связываются) в один.
В твоём случае H-файл включается по разу в каждый подключающий его C-файл. Объектные файлы получаются с копиями того массива, но компилятор при создании каждого из них об этом не знает. А вот линковщик (linker) видит две вещи с одним именем в одной глобальной области и пугается, т.к. для обеих из них есть определение.
Т.е. H-файлы сами по себе непосредственно не обрабатываются. Всё исходит от C-файлов. Ну а что делать — тебе уже сказали.
P.S.: На самом деле компиляторы данный процесс обычно оптимизируют, но поведение такое сохраняют.
| |
От: | Alexey F |
| Дата: | 07.06.09 20:46 | |
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
include-guard (те самые #ifndef/#define/#endif) нужны для других целей. А, именно, для предотвращения включения текста включаемого файла дважды в одну и ту же единицу трансляции. Такое может произойти, например, когда файл X.h включает файл Y.h, а потом включает файл Z.h, который, в свою очередь, снова подключает Y.h. Без include-guard’ов получили бы множество ошибок переопределения.
TA>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
Сэкономить место на диске? Нет, скорее сэкономить время и нервы программиста, избавляя его от перебивания одинаковых строк из файла в файл 
В Вашем случае решение ситуации в смене связывания объявляемому массиву. Как это сделать — уже описали выше (static, const, extern).
P.S. Ещё безымянные namespace могут решить проблему, но по мне лучше уж const или вынос определения в отдельную единицу трансляции.
| |
От: | TheAteist |
| Дата: | 07.06.09 21:19 | |
| Оценка: |
| |
От: | TheAteist |
| Дата: | 07.06.09 21:21 | |
| Оценка: |
| |
От: | Alexey F |
| Дата: | 07.06.09 22:36 | |
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
[offtop]
Зачем дублируете ответы? 
[/offtop]
TA>Это я понял. Я не понял почему только на массив все «крики», а не, скажем на «typedef enum assetAction;» который у меня определяется под массивом. Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
Здесь разные вещи. С помощью typedef enum Вы определяете тип.
А
определяет переменную, которая уже имеет по-умолчанию внешнее связывание, т.е. учавствует при линковке. Соответственно, получаются две переменные с одним и тем же именем, определённые в двух разных файлах трансляции. Какую прикажете выбирать линкеру? 
Иллюстрация более наглядного случая (чтобы было понятно, почему линковщик не имеет право плюнуть на это и выбрать одно из определений):
P.S. Даже если тела Ваших массивов одинаковы, для линкера — это две переменных с одним и тем же именем.
| |
От: | LaptevVV |
| Дата: | 08.06.09 07:29 | |
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>При компиляции происходят ошибки:
TA>1 — error LNK2005: _assetType already defined in customer.obj
TA>2 — fatal error LNK1169: one or more multiply defined symbols found
TA>Погуглив я понял, что компилятор вставляет 2 раз вот это
TA>
TA>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
TA>Почему тогда происходит ошибка и как ее исправить?
TA>Большое спасибо.
Я обычно делаю так:
1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
2. Пишу variable.h, в котором делаю ОБЪЯВЛЕНИЯ
3. К единицам трансляции подключаю variable.h
| |
От: | рыбак |
| Дата: | 08.06.09 10:49 | |
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
#ifndef (или #pragma once) защищает от двойного включения заголовка (.h) в одну единицу компиляции (.cpp). То есть для удачной компиляции.
У тебя же ошибка линковки. Это когда в двух разных единицах компиляции (.cpp) получился одинаковый символ.
| |
От: | Аноним |
| Дата: | 08.06.09 11:15 | |
| Оценка: |
Здравствуйте, LaptevVV, Вы писали:
LVV>Я обычно делаю так:
LVV>1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
А все классы, которые нужны в нескольких единицах трансляции выносишь в файл вроде class.cpp? Одно непонятно, откуда при таком подходе появляется больше одной единицы трансляции.
| |
От: | Юрий Жмеренецкий | ICQ 380412032 |
| Дата: | 08.06.09 11:40 | ||
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>Я не понял почему только на массив все «крики», а не, скажем на «typedef enum assetAction;» который у меня определяется под массивом.
Это enumerator-definition, а для таких (и некоторых других) определений есть список условий, при соблюдении которых уникальность (определения в пределах программы) не является обязательной (3.2/5).
TA>Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
В приведенном выше коде в файле ‘customer.h’ находится объявление функции (func), а не определение.
PS: Поищи по «One definition rule», здесь это неоднократно обсуждалось.
| |
От: | TheAteist |
| Дата: | 08.06.09 17:28 | |
| Оценка: |
Здравствуйте, Alexey F, Вы писали:
AF>P.S. Даже если тела Ваших массивов одинаковы, для линкера — это две переменных с одним и тем же именем.
Кажется я понял
Значит премерно вот так получается, да?
| |
От: | LaptevVV |
| Дата: | 09.06.09 05:18 | |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, LaptevVV, Вы писали:
LVV>>Я обычно делаю так:
LVV>>1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
А>А все классы, которые нужны в нескольких единицах трансляции выносишь в файл вроде class.cpp? Одно непонятно, откуда при таком подходе появляется больше одной единицы трансляции.
Зачем-же? Речь идет не о классах, а об общих переменных. Если они требуются, конечно.
Каждый класс — это class.h и class.cpp
Можно в class.h собрать несколько классов, но лучше разделить.
| |
От: | Аноним |
| Дата: | 09.06.09 11:23 | |
| Оценка: |
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, LaptevVV, Вы писали:
LVV>Зачем-же? Речь идет не о классах, а об общих переменных. Если они требуются, конечно.
LVV>Каждый класс — это class.h и class.cpp
LVV>Можно в class.h собрать несколько классов, но лучше разделить.
А почему лучше их разделить и почему нельзя эти рассуждения применить к общим переменным?
Источник
Write your question here. Hi, it is me again. I am getting this error and cannot figure out what I am doing wrong. It is in visual studios 2013 again BTW.
[#include «stdafx.h» // Precompiled header
#include «iostream» // Input and output stream
using namespace std; // Meaning you don’t have to put std:: before cout <<;.
int squareIntegers(); // Function Prototype
double squareDouble();
float squareFloat();
int squareIntegers(int x) { //Function
int solution; //Declaring the variable solution, which is an integer data type.
solution = x * x; // Squaring x.
return solution; //Returns solution
}
double squareDouble(double d) {
double answer;
answer = d * d;
return answer;
}
float squareFloat(float x, float y) {
float answer1;
float answer2;
answer1 = x * x;
answer2 = y * y;
return 0;
}
int main() //Main Function
{
cout << squareIntegers(22) << endl;
cout << squareDouble(12) << endl;
cout << squareFloat(132, 150) << endl; //Function call and display with value 22 (so x = 22)
system(«pause»); // Helps with displaying the output of a program.
return 0; // Returns a value.
}
code]
Put the code you need help with here.
[/code]
Last edited on
can you use code tags please?
you need to read this:
http://www.cplusplus.com/doc/tutorial/functions/
for example, you prototype:
int squareIntegers();
but you call it like this:
squareIntegers(22)
you also do not need prototype declarations if you’re implementing them before you call them.
i.e. delete these:
|
|
Last edited on
I’m trying to but it keeps displaying like that.
besides the functions issue there is also this:
|
|
why are you doing calculations and then return zero?
edit:
you also do not need this either:
#include "stdafx.h"
Last edited on
I did it because I cannot return both answer1 and answer2 twice. What is the function issue?
please read my first post. basically these lines:
|
|
are wrong, and not even needed.
I did it because I cannot return both answer1 and answer2 twice.
You need to read that link i pasted on functions.
Okay
So, I read it but and why are
[int squareIntegers(); // Function Prototype
double squareDouble();
float squareFloat();], wrong. They are function prototypes.
Also, I get an error saying to include «stdafx.h» if I don’t include it.
Also, for squareIntegers(22), I used this in my last program, and it worked fine. I have no idea what else could be the issue.
Also, how do you use the tags. I click on <>, then this comes up: , but where in the brackets do I paste my code? I pasted in the brackets and it doesn’t work. Is there a specific location in the brackets where I should paste my code?
They are function prototypes.
Yes they are, but they don’t match your functions!
This prototype:
Tells your compiler you’re going to supply a method that takes NO parameters and returns an integer. However when you get to your code:
|
|
You’re telling the compiler about a different function. This one takes an integer and returns an integer.
This issue becomes apparent when you move your functions implementations below your main function:
|
|
errors:
(10): error C2660: ‘squareIntegers’ : function does not take 1 arguments
(11): error C2660: ‘squareDouble’ : function does not take 1 arguments
(12): error C2660: ‘squareFloat’ : function does not take 2 arguments
Because your prototypes should be:
|
|
Last edited on
Okay, thanks for that, but I still have this error: «fatal error LNK1169: one or more multiply defined symbols found.»
Does this mean in my squareFloat function, I need to make a struct, return the struct name? Will that get rid of this error?
I don’t don’t get any errors when I compile your code.
Hmmmm…. Stange. I even copy and pasted the code you had and I am still getting the error:
«fatal error LNK1169: one or more multiply defined symbols found.»
Also, I still have to add #include «stdafx.h» or else I will get an error saying I am missing that.
I’m using visual studios 2013.
I got it running!
But I have two problems.
1) It says I have to return something in the squareFloat function, but whatever I return (even 0), it will show in the output display box? What can I return that will make nothing display?
2) How do I create spaces between numbers? For example, instead of 1213, how would I make this 12 13?
Okay, I figured out the spacing part, but I still need help on the return part.
Can someone please help? This is all I need and I will be done.
what is the function meant to do? «squareFloat» implies to me that you are squaring a float? i.e. it takes in one float and returns a float.
Also, I still have to add #include «stdafx.h» or else I will get an error saying I am missing that.
what kind of project have you created?? You don’t need this at all.
Last edited on
Topic archived. No new replies allowed.
Recommended Answers
Please use code tags instead, and watch spaces like in
using namespaceorelse if.#include<iostream> using namespace std; int main() { int age; char sex; cout<<"please input your age:"; cout<<"please input your sex (M/F):"; cin>> age; cin>> sex; if ( age < 100 …
Jump to Post
The same program works fine with me.
Which OS and compiler (version) are u using?
Jump to Post
There must be some information that you can see that you’re not telling us. How did you set up the project? Are there other files in it? Etc.?
Jump to Post
You can have more files, but as the linker seems to be telling you, you can’t have the same thing defined in more than one place. I don’t suppose you’d care to post all the relevant code?
Jump to Post
All 13 Replies
16 Years Ago
Please use code tags instead, and watch spaces like in using namespace or else if .
#include<iostream>
using namespace std;
int main()
{
int age;
char sex;
cout<<"please input your age:";
cout<<"please input your sex (M/F):";
cin>> age;
cin>> sex;
if ( age < 100 )
{
cout<<"you are pretty young!n";
}
else if ( age ==100 && sex == 'm' )
{
cout<<"you are pretty old,and you are male!n";
}
else if ( age ==100 && sex == 'f' )
{
cout<<"you are pretty old, and u r a female!n";
}
else
{
cout<<"You are relly old!n";
}
}
Any problem with this?
16 Years Ago
Thanks for your reply.But still after took care of spaces,it displays that same error.Please help me.I am new to programming.
#include<iostream>
usingnamespace std;
int main()
{
int age;
char sex;
cout<<"please input your age:";
cout<<"please input your sex (M/F):";
cin>> age;
cin>> sex;
if (age < 100){
cout<<"you are pretty young!n";
}else if (age == 100 && sex == 'm'){
cout<<"you are pretty old,and you are male!n";
}else if (age == 100 && sex == 'f'){
cout<<"you are pretty old, and u r a female!n";
}else{
cout<<"You are relly old!n";
}
}
Also,i don’t know,how to give programs in code.I used
~s.o.s~
2,560
Failure as a human
Team Colleague
Featured Poster
16 Years Ago
The same program works fine with me.
Which OS and compiler (version) are u using?
16 Years Ago
OS-windows.XP
Compiler-Microsoft VC++ 2005 enterprise edition
Please help me.I couldn’t able to correct that problem.
16 Years Ago
There must be some information that you can see that you’re not telling us. How did you set up the project? Are there other files in it? Etc.?
16 Years Ago
Yes,the project has 2 more files with it.I thought in one project we can place more files.
Thanks for the reply and help me.How can i run this file when more that one file is stored in same project.
16 Years Ago
You can have more files, but as the linker seems to be telling you, you can’t have the same thing defined in more than one place. I don’t suppose you’d care to post all the relevant code?
16 Years Ago
This is the full error message
Ex2agesex.obj : error LNK2005: _main already defined in Ex1Sum.obj
Ex3currencydollar.obj : error LNK2005: _main already defined in Ex1Sum.obj
C:Documents and SettingsMohan.RBCHRIT7My DocumentsVisual Studio 2005ProjectsOwnProgramsDebugOwnPrograms.exe : fatal error LNK1169: one or more multiply defined symbols found
Build log was saved at «file://c:Documents and SettingsMohan.RBCHRIT7My DocumentsVisual Studio 2005ProjectsOwnProgramsDebugBuildLog.htm»
OwnPrograms — 3 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
How would i set some file as main to run in VC++
16 Years Ago
Well there you go. You’ve got main defined in more than one file. You can only have one main . Just like the messages are saying. You need a single entry point to your program — decide where it should be.
And again, if you want help with code, it is highly advisable that you post the code you want help with.
16 Years Ago
Dave thanks for your help and apologize for not asking my question properly.I thought that fatal error would be the problem for my program.
16 Years Ago
My first program in a project is
#define _CRT_SECURE_NO_DEPRECATE//to take of scanf deprecated warning
#include<stdio.h>
#include<math.h>
//int main()
{
int a,b;
double aSquare,bSquare,sumOfSquare;
printf("input first numbern");
scanf("%d",&a);
printf("input second numbern");
scanf("%d",&b);
printf("sum %dn",a+b);
printf("average %dn",(a+b)/2);
aSquare=sqrt(a);
bSquare=sqrt(b);
sumOfSquare=aSquare+bSquare;
printf("sumOfSquare %fn",sumOfSquare);
}
As you told i have taken off main from it.and my second file is
#include <iostream>
using namespace std;
int main()
{
int age;
char sex;
cout<<"please input your age:";
cout<<"please input your sex (M/F):";
cin>> age;
cin>> sex;
//cin.ignore();
if (age < 100){
cout<<"you are pretty young!n";
}else if (age == 100 && sex == 'm'){
cout<<"you are pretty old,and you are male!n";
}else if (age == 100 && sex == 'f'){
cout<<"you are pretty old, and u r a female!n";
}else{
cout<<"You are relly old!n";
}
// cin.get();
}
how can i call the first program in the second one.Displaying two programs output in second file.Please help me.
16 Years Ago
Make it a function called something other than main , then call it from the other code.
15 Years Ago
Thanks Dave. Your answer solved my problem as well.
Reply to this topic
Be a part of the DaniWeb community
We’re a friendly, industry-focused community of developers, IT pros, digital marketers,
and technology enthusiasts meeting, networking, learning, and sharing knowledge.
Почему происходит multiply defined symbols
|
|
От: |
TheAteist |
|
| Дата: | 07.06.09 11:54 | ||
| Оценка: |
При компиляции происходят ошибки:
1 — error LNK2005: _assetType already defined in customer.obj
2 — fatal error LNK1169: one or more multiply defined symbols found
Погуглив я понял, что компилятор вставляет 2 раз вот это
const char* assetType[] = {"apartment", "shop", "house"};
но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
Почему тогда происходит ошибка и как ее исправить?
Большое спасибо.
//main.c
#include "customer.h"
void main()
{
}
//customer.h
#ifndef _CUSTOMER_H_
#define _CUSTOMER_H_
const char* assetType[] = {"apartment", "shop", "house"};
void func();
#endif
//customer.c
#include "customer.h"
void func()
{
int i;
}
Re: Почему происходит multiply defined symbols
|
|
От: |
Caracrist |
https://1pwd.org/ |
| Дата: | 07.06.09 12:10 | ||
| Оценка: |
-2 |
Re[2]: Почему происходит multiply defined symbols
|
|
От: |
Caracrist |
https://1pwd.org/ |
| Дата: | 07.06.09 12:26 | ||
| Оценка: |
+1 |
Здравствуйте, Caracrist, Вы писали:
C>this ?
C>
C>#pragma once
C>
это я прогнал
missing static…
static const char* assetType[] = {"apartment", "shop", "house"};
Re: Почему происходит multiply defined symbols
|
|
От: |
andrey.desman |
|
| Дата: | 07.06.09 12:45 | ||
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
Да, один раз, но в каждую единицу трансляции (файл .c / .cpp).
Этот так называемый include guard помогает в ситуации, когда заголовок (файл .h) включается два или более раза в одну единицу трансляции.
TA>Почему тогда происходит ошибка и как ее исправить?
Так как символ глобальный, то он «виден» и из других единиц трансляции. Но так как заголовок включен в оба сишника, то создается два символа с одним и тем же именем, чего линкер очень не любит.
Либо добавь «static», тогда в каждом сишнике будет своя копия этого массива и конфликта имен не будет.
Либо, определение в какой-нибудь один сишник, а в заголовок только объявление. Тогда будет существовать лишь одна копия этого массива.
Re: Почему происходит multiply defined symbols
|
|
От: |
Alexey F |
|
| Дата: | 07.06.09 12:51 | ||
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>При компиляции происходят ошибки:
TA>1 — error LNK2005: _assetType already defined in customer.obj
TA>2 — fatal error LNK1169: one or more multiply defined symbols found
TA>Погуглив я понял, что компилятор вставляет 2 раз вот это
TA>
TA>const char* assetType[] = {"apartment", "shop", "house"};
TA>
В дополнение к данным выше ответам:
const char* const assetType[] = {"apartment", "shop", "house"};
Так тоже будет работать (подразумевается внутреннее связывание).
TA>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
Верно. По одному разу в каждый файл, который подключил customer.h.
P.S. Если нет желания делать массив константным или внутренним для каждой единицы трансляции, то только так:
в заголовке его объявляем с extern, а определяем в отдельном .c/.cpp файле
Re[2]: Почему происходит multiply defined symbols
|
|
От: |
TheAteist |
|
| Дата: | 07.06.09 20:01 | ||
| Оценка: |
Здравствуйте, andrey.desman, Вы писали:
AD>Здравствуйте, TheAteist, Вы писали:
TA>>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
AD>Да, один раз, но в каждую единицу трансляции (файл .c / .cpp).
AD>Этот так называемый include guard помогает в ситуации, когда заголовок (файл .h) включается два или более раза в одну единицу трансляции.
1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
TA>>Почему тогда происходит ошибка и как ее исправить?
AD>Так как символ глобальный, то он «виден» и из других единиц трансляции. Но так как заголовок включен в оба сишника, то создается два символа с одним и тем же именем, чего линкер очень не любит.
AD>Либо добавь «static», тогда в каждом сишнике будет своя копия этого массива и конфликта имен не будет.
Своя копия означает
AD>Либо, определение в какой-нибудь один сишник, а в заголовок только объявление. Тогда будет существовать лишь одна копия этого массива.
Re[2]: Почему происходит multiply defined symbols
|
|
От: |
TheAteist |
|
| Дата: | 07.06.09 20:02 | ||
| Оценка: |
Здравствуйте, Alexey F, Вы писали:
AF>Здравствуйте, TheAteist, Вы писали:
TA>>При компиляции происходят ошибки:
TA>>1 — error LNK2005: _assetType already defined in customer.obj
TA>>2 — fatal error LNK1169: one or more multiply defined symbols found
TA>>Погуглив я понял, что компилятор вставляет 2 раз вот это
TA>>
TA>>const char* assetType[] = {"apartment", "shop", "house"};
TA>>
AF>В дополнение к данным выше ответам:
AF>
AF>const char* const assetType[] = {"apartment", "shop", "house"};
AF>
AF>Так тоже будет работать (подразумевается внутреннее связывание).
TA>>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
AF>Верно. По одному разу в каждый файл, который подключил customer.h.
1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
AF>P.S. Если нет желания делать массив константным или внутренним для каждой единицы трансляции, то только так:
AF>в заголовке его объявляем с extern, а определяем в отдельном .c/.cpp файле
Re[3]: Почему происходит multiply defined symbols
|
|
От: |
Kirikaza |
kirikaza.ru |
| Дата: | 07.06.09 20:35 | ||
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
TA>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
#include «x.h» лучше рассматривать как «вставить в этом месте содержимое файла x.h».
Пусть есть файл x.h:
#ifndef X_H
#define X_H
...
#endif
Если файл x.h вставлен дважды в некий C-файл
#include "x.h"
#include "x.h"
то получается вот так:
#ifndef X_H
#define X_H
...
#endif
#ifndef X_H
#define X_H
...
#endif
При этом первый #ifndef сработает, т.к. X_H ещё не определена, и определит X_H. А второй #ifndef не сработает, т.к. X_H уже определена.
Когда происходит компиляция, препроцессор берёт C-файл выполняет вот эту подстановку и оставляет код внутри первого #if и выкидывает внутри второго. Затем полученный код отдаётся компилятору, который компилирует и получает объектный файл. Затем берётся второй C-файл и для него независимо от первого C-файла процедура повторяется заново (т.е. в самом начале обработки препроцессором второго C-файла X_H никем не была определена). Когда все объектные файлы получены, они все линкуются (связываются) в один.
В твоём случае H-файл включается по разу в каждый подключающий его C-файл. Объектные файлы получаются с копиями того массива, но компилятор при создании каждого из них об этом не знает. А вот линковщик (linker) видит две вещи с одним именем в одной глобальной области и пугается, т.к. для обеих из них есть определение.
Т.е. H-файлы сами по себе непосредственно не обрабатываются. Всё исходит от C-файлов. Ну а что делать — тебе уже сказали.
P.S.: На самом деле компиляторы данный процесс обычно оптимизируют, но поведение такое сохраняют.
Re[3]: Почему происходит multiply defined symbols
|
|
От: |
Alexey F |
|
| Дата: | 07.06.09 20:46 | ||
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
include-guard (те самые #ifndef/#define/#endif) нужны для других целей. А, именно, для предотвращения включения текста включаемого файла дважды в одну и ту же единицу трансляции. Такое может произойти, например, когда файл X.h включает файл Y.h, а потом включает файл Z.h, который, в свою очередь, снова подключает Y.h. Без include-guard’ов получили бы множество ошибок переопределения.
TA>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
Сэкономить место на диске? Нет, скорее сэкономить время и нервы программиста, избавляя его от перебивания одинаковых строк из файла в файл
В Вашем случае решение ситуации в смене связывания объявляемому массиву. Как это сделать — уже описали выше (static, const, extern).
P.S. Ещё безымянные namespace могут решить проблему, но по мне лучше уж const или вынос определения в отдельную единицу трансляции.
Re[4]: Почему происходит multiply defined symbols
|
|
От: |
TheAteist |
|
| Дата: | 07.06.09 21:19 | ||
| Оценка: |
Здравствуйте, Kirikaza, Вы писали:
K>Здравствуйте, TheAteist, Вы писали:
TA>>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
TA>>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
K>#include «x.h» лучше рассматривать как «вставить в этом месте содержимое файла x.h».
K>Пусть есть файл x.h:
K>
#ifndef X_H
K>#define X_H
K>...
K>#endif
K>
K>Если файл x.h вставлен дважды в некий C-файл
K>
#include "x.h"
K>#include "x.h"
K>то получается вот так:
K>
#ifndef X_H
K>#define X_H
K>...
K>#endif
K>#ifndef X_H
K>#define X_H
K>...
K>#endif
K>При этом первый #ifndef сработает, т.к. X_H ещё не определена, и определит X_H. А второй #ifndef не сработает, т.к. X_H уже определена.
K>Когда происходит компиляция, препроцессор берёт C-файл выполняет вот эту подстановку и оставляет код внутри первого #if и выкидывает внутри второго. Затем полученный код отдаётся компилятору, который компилирует и получает объектный файл. Затем берётся второй C-файл и для него независимо от первого C-файла процедура повторяется заново (т.е. в самом начале обработки препроцессором второго C-файла X_H никем не была определена). Когда все объектные файлы получены, они все линкуются (связываются) в один.
K>В твоём случае H-файл включается по разу в каждый подключающий его C-файл. Объектные файлы получаются с копиями того массива, но компилятор при создании каждого из них об этом не знает. А вот линковщик (linker) видит две вещи с одним именем в одной глобальной области и пугается, т.к. для обеих из них есть определение.
Это я понял. Я не понял почему только на массив все «крики», а не, скажем на «typedef enum{eBuy, eSell, eRent} assetAction;» который у меня определяется под массивом. Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
K>Т.е. H-файлы сами по себе непосредственно не обрабатываются. Всё исходит от C-файлов. Ну а что делать — тебе уже сказали.
K>P.S.: На самом деле компиляторы данный процесс обычно оптимизируют, но поведение такое сохраняют.
Re[4]: Почему происходит multiply defined symbols
|
|
От: |
TheAteist |
|
| Дата: | 07.06.09 21:21 | ||
| Оценка: |
Здравствуйте, Alexey F, Вы писали:
AF>Здравствуйте, TheAteist, Вы писали:
TA>>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
AF>include-guard (те самые #ifndef/#define/#endif) нужны для других целей. А, именно, для предотвращения включения текста включаемого файла дважды в одну и ту же единицу трансляции. Такое может произойти, например, когда файл X.h включает файл Y.h, а потом включает файл Z.h, который, в свою очередь, снова подключает Y.h. Без include-guard’ов получили бы множество ошибок переопределения.
Это я понял. Я не понял почему только на массив все «крики», а не, скажем на «typedef enum{eBuy, eSell, eRent} assetAction;» который у меня определяется под массивом. Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
TA>>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
AF>Сэкономить место на диске? Нет, скорее сэкономить время и нервы программиста, избавляя его от перебивания одинаковых строк из файла в файл
AF>В Вашем случае решение ситуации в смене связывания объявляемому массиву. Как это сделать — уже описали выше (static, const, extern).
AF>P.S. Ещё безымянные namespace могут решить проблему, но по мне лучше уж const или вынос определения в отдельную единицу трансляции.
Re[5]: Почему происходит multiply defined symbols
|
|
От: |
Alexey F |
|
| Дата: | 07.06.09 22:36 | ||
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
[offtop]
Зачем дублируете ответы? И оверквотинг лишний.
[/offtop]
TA>Это я понял. Я не понял почему только на массив все «крики», а не, скажем на «typedef enum{eBuy, eSell, eRent} assetAction;» который у меня определяется под массивом. Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
Здесь разные вещи. С помощью typedef enum Вы определяете тип.
А
const char* assetType[] = {"apartment", "shop", "house"};
определяет переменную, которая уже имеет по-умолчанию внешнее связывание, т.е. учавствует при линковке. Соответственно, получаются две переменные с одним и тем же именем, определённые в двух разных файлах трансляции. Какую прикажете выбирать линкеру?
Иллюстрация более наглядного случая (чтобы было понятно, почему линковщик не имеет право плюнуть на это и выбрать одно из определений):
// 1.cpp
int val = 0; // фактически, эта строка могла быть в h-файле
// 2.cpp
int val = 42; // фактически, эта строка могла быть в h-файле
// 3.cpp
extern int val;
...
printf ( "%d", val ); // Ой! А какая val?
P.S. Даже если тела Ваших массивов одинаковы, для линкера — это две переменных с одним и тем же именем.
Re: Почему происходит multiply defined symbols
|
|
От: |
LaptevVV |
|
| Дата: | 08.06.09 07:29 | ||
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>При компиляции происходят ошибки:
TA>1 — error LNK2005: _assetType already defined in customer.obj
TA>2 — fatal error LNK1169: one or more multiply defined symbols found
TA>Погуглив я понял, что компилятор вставляет 2 раз вот это
TA>
TA>const char* assetType[] = {"apartment", "shop", "house"};
TA>
TA>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
TA>Почему тогда происходит ошибка и как ее исправить?
TA>Большое спасибо.
Я обычно делаю так:
1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
2. Пишу variable.h, в котором делаю ОБЪЯВЛЕНИЯ
extern переменная/константа;
3. К единицам трансляции подключаю variable.h
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: Почему происходит multiply defined symbols
|
|
От: |
рыбак |
|
| Дата: | 08.06.09 10:49 | ||
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
#ifndef (или #pragma once) защищает от двойного включения заголовка (.h) в одну единицу компиляции (.cpp). То есть для удачной компиляции.
У тебя же ошибка линковки. Это когда в двух разных единицах компиляции (.cpp) получился одинаковый символ.
Re[2]: Почему происходит multiply defined symbols
|
|
От: | Аноним | |
| Дата: | 08.06.09 11:15 | ||
| Оценка: |
Здравствуйте, LaptevVV, Вы писали:
LVV>Я обычно делаю так:
LVV>1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
А все классы, которые нужны в нескольких единицах трансляции выносишь в файл вроде class.cpp? Одно непонятно, откуда при таком подходе появляется больше одной единицы трансляции.
Re[5]: Почему происходит multiply defined symbols
|
|
От: |
Юрий Жмеренецкий |
ICQ 380412032 |
| Дата: | 08.06.09 11:40 | ||
| Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>Я не понял почему только на массив все «крики», а не, скажем на «typedef enum{eBuy, eSell, eRent} assetAction;» который у меня определяется под массивом.
Это enumerator-definition, а для таких (и некоторых других) определений есть список условий, при соблюдении которых уникальность (определения в пределах программы) не является обязательной (3.2/5).
TA>Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
В приведенном выше коде в файле ‘customer.h’ находится объявление функции (func), а не определение.
PS: Поищи по «One definition rule», здесь это неоднократно обсуждалось.
Re[6]: Почему происходит multiply defined symbols
|
|
От: |
TheAteist |
|
| Дата: | 08.06.09 17:28 | ||
| Оценка: |
Здравствуйте, Alexey F, Вы писали:
AF>P.S. Даже если тела Ваших массивов одинаковы, для линкера — это две переменных с одним и тем же именем.
Кажется я понял
Значит премерно вот так получается, да?
//main.obj
const char* assetType[] = {"apartment", "shop", "house"};
void func();
void main()
{
}
//customer.obj
const char* assetType[] = {"apartment", "shop", "house"};
void func();
void func()
{
int i;
}
Re[3]: Почему происходит multiply defined symbols
|
|
От: |
LaptevVV |
|
| Дата: | 09.06.09 05:18 | ||
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, LaptevVV, Вы писали:
LVV>>Я обычно делаю так:
LVV>>1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
А>А все классы, которые нужны в нескольких единицах трансляции выносишь в файл вроде class.cpp? Одно непонятно, откуда при таком подходе появляется больше одной единицы трансляции.
Зачем-же? Речь идет не о классах, а об общих переменных. Если они требуются, конечно.
Каждый класс — это class.h и class.cpp
Можно в class.h собрать несколько классов, но лучше разделить.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[4]: Почему происходит multiply defined symbols
|
|
От: | Аноним | |
| Дата: | 09.06.09 11:23 | ||
| Оценка: |
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, LaptevVV, Вы писали:
LVV>Зачем-же? Речь идет не о классах, а об общих переменных. Если они требуются, конечно.
LVV>Каждый класс — это class.h и class.cpp
LVV>Можно в class.h собрать несколько классов, но лучше разделить.
А почему лучше их разделить и почему нельзя эти рассуждения применить к общим переменным?


- Переместить
- Удалить
- Выделить ветку
Пока на собственное сообщение не было ответов, его можно удалить.



