I have a simple for loop (though it is not the only component within the method) that is compiled with GNU 4.8.1.10 compiler with debugging option is off and optimization levels O-0, O-2 and O-3 distinctively. The loop is as below:
const int iMyConst = 10; // defined in another header
void myFunc(uint8_t ui8InputNum)
{
// some stuff
for(int i=static_cast<int>(ui8InputNum); i<iMyConst; i++)
{ // loop content
}
}
What happens is that, when I call myFunc(10) (equal to iMyConst), the for loop is executed. This is not the expected behaviour. Inside the loop I printed the variable values as well. They are printed as expected but with an exception: i<iMyConst came out to be true where i was printed as 10. Moreover, I forced all process to run on single core, the unexpected behaviour happened again.
I ran the code in debug mode, and saw that the loop is not executed as expected. Then I defined the loop variable as volatile int i, this time the loop is not executed as well.
The problem might sound odd but it is all what happened. What is the cause of this problem? The system is 64-bit and has 12 cores.
// main.cpp
//============================================================================
// Name : loopProblem.cpp
//============================================================================
#include "a.h"
#include "b.h"
#include <iostream>
int main() {
a* myA = new a;
b* myB = new b;
myB->itsA = myA;
myB->dummyFunc();
delete myA;
delete myB;
return 0;
}
// a.h
#ifndef A_H_
#define A_H_
#include <stdint.h>
// #include <cstdint> not available in c++03
class a
{
public:
a();
~a();
void myFunc(uint8_t ui8InputNum);
};
#endif /* A_H_ */
// a.cpp
#include "a.h"
#include "c.h"
#include <cstdio>
a::a()
{
}
a::~a()
{
}
void a::myFunc(uint8_t ui8InputNum)
{
// some stuff
for(int i=static_cast<int>(ui8InputNum); i<iMyConst; i++)
{
printf("i: %d, comp: %d\n", i, (i<iMyConst));
}
}
// b.h
#ifndef B_H_
#define B_H_
class a;
class b {
public:
b();
~b();
a* itsA;
void dummyFunc();
};
#endif /* B_H_ */
// b.cpp
#include "b.h"
#include "a.h"
#include <cstddef>
b::b() : itsA(NULL)
{
}
b::~b()
{
}
void b::dummyFunc() {
itsA->myFunc(10);
}
// c.h
#ifndef C_H_
#define C_H_
const int iMyConst = 10;
#endif /* C_H_ */
Related
Updated:
I created a project that can 100% reproduce the problem.
1. DLL Project
I named this DLL project TestDLL
The most important codes:
AddC.h:
#pragma once
class CTestDLL;
#include <string>
using namespace std;
//use AddC somewhere inside the DLL internally
class AddC{
private:
string _fake_string_ = "_fake_string_";
void _fake_method_();
public:
void add2Result(CTestDLL* test);
};
AddC.cpp:
#include "pch.h"
#include "AddC.h"
#include "TestDLL.h"
void AddC::_fake_method_()
{
_fake_string_ = "_fake_string_in_fake_method_";
}
void AddC::add2Result(CTestDLL * test)
{
test->result += 1;
}
TestDLL.h:
#ifdef TESTDLL_EXPORTS
#define TESTDLL_API __declspec(dllexport)
#else
#define TESTDLL_API __declspec(dllimport)
#endif
#include "AddC.h"
class TESTDLL_API CTestDLL {
public:
CTestDLL(void);
void test();
int getResult();
private:
friend class AddC;
private:
AddC addc;
int result=0;
};
TestDLL.cpp:
#include "pch.h"
#include "framework.h"
#include "TestDLL.h"
CTestDLL::CTestDLL(){
result = 0;
return;
}
void CTestDLL::test(){
auto _this = this;
addc.add2Result(_this);
}
int CTestDLL::getResult(){
return this->result;
}
2. SimpleTestApplication Project
The TestApplication has only two code files.
dll.hpp:
#pragma once
class AddC{};
class CTestDLL {
public:
CTestDLL(void);
void test();
int getResult();
private:
int result = 0;
AddC addc;
};
app.cpp:
#include "dll.hpp"
#include <iostream>
using namespace std;
#pragma comment(lib, "TESTDLL.lib")
int main(){
CTestDLL test;
test.test();
test.test();
test.test();
cout << test.getResult() << endl;
return 0;
}
The testApplication compile and link successfully.
But,But.When the main function exits, the program throws an exception that the stack was corrupted.
The key point is 'fake string_' variable in AddC.
But I don't how to do.
Previous:
Like this on a dll project:
class B;
class C;
class __declspec(dllexport) A{
private:
friend class B;
friend class C;
}
And I compiled the dll project;
Use .dll,.lib and the following header file on a simple console project:
dll.hpp:
class __declspec(dllimport) A{
private:
friend class B;
friend class C;
}
The main func:
#include "dll.hpp"
#pragma comment(lib, "dll.lib")
int main(){
A a;
return 0;
}
It compiled successfully.But the program threw an exception when running:
Run-Time Check Failure #2 - Stack around the variable 'a' was corrupted.
Who can help me?
#selbie's suggestion regarding the factory function / method creating is the cleanest way to go (would prevent you from ending in situations like this), and design-wise it makes the most sense, but it's not mandatory (after all there are lots of .dlls out there exporting classes).
What jumped into my eye, was the fact that (in both scenarios) a header file was present in the application that was (somewhat) duplicating the (main) one in the .dll. Every .dll comes with its own header file(s), and those are the ones that should be used by its clients (apps or other dlls). They are both maintained by the dll creators, and when updates come, they are both in sync. Doing otherwise is not scalable (each app creating its own header file version), makes no sense, and I don't know why would anyone do something like that.
With this in mind, I recreated the environment (both scenarios), doing things the right way, and everything worked fine, then I worked my way to your (wrong) way, trying to identify the culprit.
Example (numbered the 2 scenarios: 00 and 01):
DllExport.h:
#pragma once
#if defined(_WIN32)
# if defined(DLL_STATIC)
# define DLL_EXPORT_API
# else
# if defined(DLL_EXPORTS)
# define DLL_EXPORT_API __declspec(dllexport)
# else
# define DLL_EXPORT_API __declspec(dllimport)
# endif
# endif
#else
# define DLL_EXPORT_API
#endif
Scenario 00:
AddC.hpp:
#pragma once
#include <string>
using namespace std;
class CTestDLL;
//use AddC somewhere inside the DLL internally
class AddC {
private:
string _fake_string_ = "_fake_string_";
void _fake_method_();
public:
void add2Result(CTestDLL *pTest);
};
TestDLL.hpp:
#pragma once
#include <DllExport.h>
#include <AddC.hpp>
class DLL_EXPORT_API CTestDLL {
public:
CTestDLL();
void test();
int getResult();
private:
friend class AddC;
private:
AddC addc;
int result = 0;
};
dll:
AddC.cpp:
#include "AddC.hpp"
#include "TestDLL.hpp"
void AddC::_fake_method_()
{
_fake_string_ = "_fake_string_in_fake_method_";
}
void AddC::add2Result(CTestDLL *pTest)
{
pTest->result += 1;
}
TestDLL.cpp:
#define DLL_EXPORTS
#include <TestDLL.hpp>
CTestDLL::CTestDLL()
{
result = 0;
return;
}
void CTestDLL::test()
{
auto _this = this;
addc.add2Result(_this);
}
int CTestDLL::getResult()
{
return this->result;
}
app:
dll.hpp:
#pragma once
#define _WRONG_INNER_CLASS
#if defined(_WRONG_INNER_CLASS)
class AddC {};
#else
# include <AddC.hpp>
#endif
#define _WRONG_IMPORT_DIRECTIVE
#if defined(_WRONG_IMPORT_DIRECTIVE)
# define CLASS_IMPORT_API
#else
# define CLASS_IMPORT_API __declspec(dllimport)
#endif
class CLASS_IMPORT_API CTestDLL {
public:
CTestDLL();
void test();
int getResult();
private:
int result = 0;
AddC addc;
};
main.cpp:
#include <iostream>
#include <cstdio>
#define _DUPLICATE_DLL_HEADER_FILE
#if defined (_DUPLICATE_DLL_HEADER_FILE)
# include <dll.hpp>
#else
# include <TestDll.hpp>
#endif
#pragma comment(lib, "dll.lib")
using std::cout;
using std::endl;
int main()
{
CTestDLL test;
test.test();
test.test();
test.test();
cout << test.getResult() << endl;
printf("Done.\n");
return 0;
}
Scenario 01:
dll.hpp:
#pragma once
#include <DllExport.h>
class DLL_EXPORT_API A {
private:
friend class B;
friend class C;
};
dll:
dll.cpp:
#define DLL_EXPORTS
class B;
class C;
#include <dll.hpp>
app:
AppDll.hpp:
#pragma once
#define CLASS_IMPORT_API __declspec(dllimport)
class CLASS_IMPORT_API A {
private:
friend class B;
friend class C;
};
main.cpp:
#include <cstdio>
#define _DUPLICATE_DLL_HEADER_FILE
#if defined (_DUPLICATE_DLL_HEADER_FILE)
# include "AppDll.hpp"
#else
# include <dll.hpp>
#endif
#pragma comment(lib, "dll.lib")
int main()
{
A a;
printf("Done.\n");
return 0;
}
Project structure:
Results:
Scenario 00:
There were 2 mistakes:
Class AddC redefinition
Missing import directive for CTestDll
In dll.hpp there are 2 _WRONG* macros. If both are commented, it will work
Scenario 01:
I couldn't reproduce the crash (with / without friends)
Note: Tested with VStudio 2022 and MSSDK 10.0.22000.0
I have this situation where I'm trying to pass a map after I populated it, from a file to a class:
A.h - a normal header file where I have a function prototype and a map
#include <unordered_map>
func1();
static std::unordered_map<glm::ivec3, Chunk*, KeyHasher> chunks;
A.cpp
#include "A.h"
func1() {
// ...
chunks.insert(pair<glm::ivec3, Chunk*>(pos, chunk));
cout << chunks.size(); // here I have the right size
// ...
}
B.h
#include "A.h"
class B {
public:
my_func();
}
B.cpp
B::my_func() {
// ...
cout << chunks.size(); // size is 0
for (auto& c : chunks) {
// ... do something
}
}
My question is, why in B.cpp chunks map arrives empty? I thought that if I use static this will solve my problem. Thank you for your time!
You are declaring the chunks variable as static in A.h. That is the problem.
Every .cpp that #include's A.h will get its own copy of the chunks variable. That is why chunks is populated in A.cpp but is empty in B.cpp.
If you want to share the chunks variable across translation units, it needs to be declared as extern instead of static, and then defined in one of .cpp files, eg:
A.h
#include <unordered_map>
func1();
extern std::unordered_map<glm::ivec3, Chunk*, KeyHasher> chunks;
A.cpp
#include "A.h"
std::unordered_map<glm::ivec3, Chunk*, KeyHasher> chunks;
func1() {
// ...
chunks.insert(pair<glm::ivec3, Chunk*>(pos, chunk));
cout << chunks.size(); // here I have the right size
// ...
}
B.h
class B {
public:
my_func();
};
B.cpp
#include "B.h"
#include "A.h"
B::my_func() {
// ...
cout << chunks.size(); // here I have the right size
for (auto& c : chunks) {
// ... do something
}
}
The thing is that I am trying to have a global constant variable for all the .hand .cpp files, but when I do this I got the error:
array bound is not an integer constant before ‘]’ token
I do not understand this because Z is a constant. When I do this with just one file it works. What am I doing wrong?
Number.h
#include <iostream>
extern const int Z;
a.cpp
#include <iostream>
#include "b.h"
#include "c.h"
#include "Number.h"
using namespace std;
int main() {
const int Z = 5;
b Objeto1;
c Objeto2;
double H[Z][Z];
Objeto1.Algo(H);
Objeto2.Imprimir(H);
return 0;
}
b.h
#include <iostream>
#include "Number.h"
class b {
public:
void Algo(double[Z][Z]);
};
b.cpp
#include <iostream>
#include "b.h"
#include "Number.h"
using namespace std;
void b::Algo(double H[Z][Z]) {
for(int a = 0; a < Z; a++) {
for(int b = 0; b < Z; b++) {
H[a][b] = Z;
cout << H[a][b] << endl;
}
}
}
c.h
#include <iostream>
#include "Number.h"
class c {
public:
void Imprimir(double H[Z][Z]);
};
c.cpp
#include <iostream>
#include "c.h"
#include "Number.h"
using namespace std;
void c::Imprimir(double V[Z][Z]) {
cout << "dfs" << endl;
}
I know that the code does not make any sense, but I am just trying to understand how I could have a constant for all the files. I really appreciate your help.
Use of
extern const int Z;
is perfectly fine. However, you can't use Z to define an array. Hence, use of Z in the following line, and similar other lines, is incorrect.
class b{
public:
void Algo(double[Z][Z]);
};
The size of arrays must be known at compiler time. With the extern declaration you have provided, that is not true.
The use of extern const is justified only when you wish to define the value at run time and expect the value to not change until the program ends.
If you simply wish to use it as a token for defining arrays, remove the extern and set its value also. Use:
const int Z = 5;
Sorry for the noob question..
devf.h
#ifndef DEVF_H
#define DEVF_H
#include <string>
struct A {
int ax();
std::string ay(std::string jj);
};
struct B {
struct A* f;
int bx() {
return f->ax();
}
std::string by(std::string jj){
return f->ay(jj);
}
};
#endif // DEVF_H
devf.cpp
#include "devf.h"
int A::ax() {
return 5;
}
std::string A::ay(std::string jj){
return jj;
}
I get this error:
multiple definition of `A::ax()'
multiple definition of `A::ay(std::string)'
How can I solve this problem? I want the definitions of ax and ay functions in header file and the implementions in .cpp
Try doing this with your code:
devf.h
#ifndef DEVF_H // Add this line
#define DEVF_H // Add this line
// #include <iostream> // removed this as not needed from what is shown
#include <string> // added this as is needed
struct A {
int ax() const; // added const as it doesn't change
std::string ay( const std::string& jj ) const; // changed string to const ref & added const
};
struct B {
/*struct*/ A* f; // keyword struct not needed here.
int bx() const { // added const
return f->ax();
}
std::string by( const std::string& jj ) const { // changed to const ref & added const
return f->ay( jj );
}
};
#endif // !DEVF_H // Add this line
devf.cpp
#include "devf.h"
int A::ax() const {
return 5;
}
std::string A::ay( const std::string& jj ) const {
return jj;
}
Then you asked this or made this statement:
How can I solve this problem? I want the definitions of ax and ay functions in header file and the implementions in .cpp
devf.h
#ifndef DEVF_H
#define DEVF_H
#include <string>
struct A {
int ax() const;
std::string ay( const std::string& jj ) const;
};
struct B {
A* f;
int bx() const;
std::string by( const std::string& jj ) const;
};
#endif // !DEVF_H
devf.cpp
#include "devf.h"
int A::ax() const {
return 5;
}
std::string A::ay( const std::string& jj ) const {
return jj;
}
int B::bx() const {
return f->ax();
}
std::string B::by( const std::string& ) const {
return f->ay( jj );
}
This should help from what you have shown.
I've tried it with this:
main.cpp
#include <iostream>
#include "devf.h"
int main() {
B b;
std::cout << b.bx() << std::endl;
std::cout << b.by( "hello world" ) << std::endl;
std::cout << "\nPress any key and enter to quit." << std::endl;
char q;
std::cin >> q;
return 0;
}
output
5
hello world
Press any key and enter to quit.
- EDIT
I asked the OP: Are you including other header files?
The OP answered with:
Yes, the header "devf.h" is included in other headers
And I believe this is where the OP's problem resides. I believe that the OP is a victim of Circular Includes which will result in multiple definitions.
Example:
A.h
#ifndef A_H
#define A_H
#include "B.h" // circular include
struct A {
int a;
B b;
};
#endif // !A_H
B.h
#ifndef B_H
#define B_H
#include "A.h" // circular include
struct B {
int b;
};
#endif // !B_H
To resolve this circular include problem...
You need to use class or struct prototypes - forward declarations in the headers; works with pointer & reference types.
Only include other header files within a header file if the definition not the declaration is needed.
Once you have the class or struct's forward declaration in the header file
remove that class's include directive and put it within its cpp file
fixing the above example:
A.h
#ifndef A_H
#define A_H
// Since A has a pointer to B we remove the include from here
// and replace it with a forward declaration or class prototype...
// #include "b.h" // cicular include
class B;
struct A {
int a;
B b;
};
#endif // !A_H
A.cpp
#include "A.h"
#include "B.h" // moved the include to here - prevents circular includes
B.h
#ifndef B_H
#define B_H
// Since B does not require A we can omit this all together.
//#include "A.h" // circular include
struct B {
int b;
};
#endif // !B_H
B.cpp
#include "B.h"
You can refer to this Q & A Resolve build errors due to circular dependency amongst classes on stack for a more detailed explanation.
Once you go through the rest of your code base and fix all of the circular includes you should have no error as the above set of classes do compile and run without error.
I have the following files.
a.h:
#ifndef __A__
#define __A__
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
class A: public boost::enable_shared_from_this<A>{
public:
void somefunction();
};
#endif
a.cpp:
#include "a.h"
#include "b.h"
void A::somefunction()
{
Node new_node;
new_node.id_ = 1;
new_node.ptr = shared_from_this();
C* c = C::GetInstance();
c->addNode(new_node);
}
b.h:
#ifndef __B__
#define __B__
#include "a.h"
#include <vector>
typedef boost::shared_ptr<A> a_ptr;
struct Node{
size_t id_;
a_ptr ptr;
};
class C {
public:
static C *GetInstance(){
if(m_pInstance == nullptr){
m_pInstance = new C();
}
return m_pInstance;
}
void addNode(Node& node);
void show();
private:
static C* m_pInstance;
std::vector<Node> nodes_;
};
#endif
b.cpp:
#include "b.h"
#include <iostream>
C* C::m_pInstance = nullptr;
void C::addNode(Node& node){
nodes_.push_back(node);
}
void C::show(){
for(size_t i=0; i< nodes_.size(); i++){
if(nodes_[i].ptr != nullptr)
std::cout << nodes_[i].id_ << " " << "pointer not null" << std::endl;
}
}
main.cpp:
#include "a.h"
#include "b.h"
int main(){
A a_tmp;
a_tmp.somefunction();
C* c_tmp = C::GetInstance();
c_tmp->show();
return 0;
}
What I want to do is to use a struct to store the pointer of class A instance. But I cannot resolve the relationship between these files. Can someone give me some ideas ?
UPDATE:
The problem is, when I compile these files. I got
In b.h, error: ‘A’ was not declared in this scope typedef boost::shared_ptr<A> a_ptr;
UPDATE:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_weak_ptr> >'
A a_tmp;
a_tmp.somefunction();
This will not work. Since A::someFunction calls shared_from_this, there must exist at least one shared_ptr to any A object on which you call someFunction. Change this to:
boost::shared_ptr<A> a_tmp(boost::make_shared<A>());
a_tmp->someFunction();