I've got a simple problem I think. But I am unable to solve it so far as I am new to C++ programming. I have created a new C++ project to make the code as short and simple as possible (because the original code is much much longer) while keeping the problem I have. I have searched on Stackoverflow and Google and read about 50 related problems but nothing so far helped me fix it. Putting everything in one cc and one h file works, but is not what I prefer doing. Thanks in advance for the help.
I am using Ubuntu 14.04 / Code::Blocks 13.12 / gcc and g++ 4.8.2
The problem is that I want to access the function inside a class defined in a different file and while compiling works (due to the extern in file1.h) linking fails. If I just put "Simple S1;" instead of "extern Simple S1;" in file1.h and remove it from file1.cc I get a multiple declaration error which is expected. Apparently the "extern" trick doesn't work with classes while it works great with variables.
file1.h:
#ifndef FILE1_H
#define FILE1_H
class Simple
{
private:
unsigned int length = 10;
public:
void SetLength(unsigned int l) {length = l;}
unsigned int GetLength() {return length;}
};
extern Simple S1;
#endif
file1.cc:
#include <iostream>
#include "file1.h"
#include "file2.h"
int main()
{
Simple S1;
unsigned int l = GetL();
std::cout << "length=" << l << "\n";
l = 20;
l = GetL();
std::cout << "length=" << l << "\n";
return 0;
}
file2.h:
#ifndef FILE2_H
#define FILE2_H
unsigned int GetL();
#endif
file2.cc:
#include "file1.h"
#include "file2.h"
unsigned int GetL()
{
return S1.GetLength();
}
build commands and error:
g++ -std=c++11 -Wall -fexceptions -g -c file1.cc -o obj/Debug/file1.o
g++ -std=c++11 -Wall -fexceptions -g -c file2.cc -o obj/Debug/file2.o
g++ -o bin/Debug/Test obj/Debug/file1.o obj/Debug/file2.o
obj/Debug/file2.o: In function `GetL()':
file2.cc:6: undefined reference to `S1'
collect2: error: ld returned 1 exit status
If S1 is global it must be defined at global scope, not inside main() which creates a new instance local to that function.
Put Simple S1; before main() in your function.
#include <iostream>
#include "file1.h"
#include "file2.h"
Simple S1;
int main()
{
unsigned int l = GetL();
std::cout << "length=" << l << "\n";
l = 20;
l = GetL();
std::cout << "length=" << l << "\n";
return 0;
}
extern Simple S1;
This declaration promises there is a global object S1 of type Simple somewhere else in the code. But you never define such an object. The "closest" you come to that is the local variable S1 inside main(), but of course, that's an entirely different things.
So just move the definition of S1 outside of main():
Simple S1;
int main()
{
unsigned int l = GetL();
std::cout << "length=" << l << "\n";
l = 20;
l = GetL();
std::cout << "length=" << l << "\n";
return 0;
}
Related
I know what "forward function declaration" means, but I want get the same with variables.
I have this code snippet:
#include <iostream>
int x;
int main()
{
std::cout << x << std::endl; // I want get printed "2" but I get compile error
return 0;
}
**x = 2;**
In the std::cout I want print "2" value, but trying to compile this I get this compile error: error: 'x' does not name a type.
While this doesn't appear somthing of programmatically impossible, I can't compile successfully.
So what is the right form to write this and obtain a forward variable declaration?
Variable declarations need extern. Variable definitions need the type, like declarations. Example:
#include <iostream>
extern int x;
int main()
{
std::cout << x << '\n';
}
int x = 2;
Normally you'd use extern to access a variable from a different translation unit (i.e. from a different .cpp file), so this is mostly an artifical example.
You can declare
extern int x;
in this file, and in some other file
int x = 2;
You could use Class and declare variable inside. Also, anonymous namespace is needed as Vlad said. Example:
#include<iostream>
namespace
{
class MyClass
{
public:
static int x;
};
}
int main()
{
std::cout << MyClass::x;
}
int MyClass::x = 2;
I am learning C++ on a linux machine. I just tried “int i();” to declare a function but I forgot to define it. But to my surprise, this code can be compiled and output 1. I feel very confused. I tried “int I{};”, it still compiled with no errors. Please help to explain. Thanks in advance.
//test1.cpp
#include <iostream>
int main(void)
{
int i{};
std::cout << i << std::endl;
return 0;
}
g++ test1.cpp
./a.out
Output is: 0
//test2.cpp
#include <iostream>
int main(void)
{
int i();
std::cout << i << std::endl;
return 0;
}
g++ test2.cpp
./a.out
Output is : 1
In your first example, you define a variable named i, and value-initialise it, which for int means zero-initialisation.
int i{}; // defines i, initialised to zero
In your second example, you declare a function named i, which takes no parameters, and return int:
int i(); // declares a function
When you print this:
std::cout << i << std::endl;
i first get converted to bool (i decays to a function non-nullptr pointer, then it becomes true), and then printed as an integer, that's why you get 1. The compiler can make this conversion without the definition of i (as the result is always true), that's why you got no linker error.
If your intent was to call this function, and print the result, you'll need to use i():
std::cout << i() << std::endl;
This, of course, needs i's definition.
In your code:
//test1.cpp
#include <iostream>
int main(void)
{
int i{};
std::cout << i << std::endl;
return 0;
}
You are not actually declaring a function without defining it. The line of code int i{}; within the main() function here is a variable of type int named i and you are using a brace initializer list to initialize the variable i with out any values and in most cases could be 0 but can vary by compiler.
//test2.cpp
#include <iostream>
int main(void)
{
int i();
std::cout << i << std::endl;
return 0;
}
In this situation it is basically the same thing. You are within main() and by the rules of the language "you can not declare-define a function within a function", so this results in a declaration - definition of a variable. The only difference here is you are not using a brace initializer list here you are using it's ctor constructor called value initialization. Again you are not passing any values to it and in your case it's assigning an arbitrary value of 1.
Now if your code looked like this:
#include <iostream>
int i();
int main() {
std::cout << i() << '\n';
return 0;
}
This would fail to compile because the function i is declared but not defined. However if you did this:
#include <iostream>
// The text in quotes is not meant to be a string literal. It
// is the message of the text that represents any integer X.
int i() { return /*"some int value"*/ 1; }
int main() {
std::cout << i() << '\n';
return 0;
}
This would compile and run perfectly fine because the function i is both declared and defined.
I am having difficulty accessing a non-static member function from a function pointer and can't quite figure out my syntax issue. When attempting to compile as seen below I receive "error: fnc_ptr not declared in this scope." and when if the code is modified to not access the function it should point to it compiles and will print out 1 for bar.fn_ptr .To compile I used:
g++ -std=c++11 -Wall example.cpp foo.cpp
The split file structure/namespace is just meant to emulate the same conditions as my original issue.
example.cpp
#include "foo.h"
#include <iostream>
int main(int argc, char* argv[]){
pizza::foo bar;
bar.fn_ptr = &pizza::foo::fnc_one;
std::cout << (bar.*fn_ptr)(1) << std::endl;
return 0;
}
foo.cpp
#include <cmath>
#include "foo.h"
namespace pizza{
double foo::fnc_one(double x){
return pow(x,3) - x + 2;
}
}
foo.h
namespace pizza{
class foo{
public:
double (foo::*fn_ptr)(double);
double fnc_one(double);
foo(){
fn_ptr = 0;
}
};
}
A very similar question can be found here, with additional reference here.
You are missing bar. when referring to fn_ptr which is an attribute of that object. Change it to:
std::cout << (bar.*(bar.fn_ptr))(1) << std::endl;
And it works.
I also recommend reading this FAQ on the subject: https://isocpp.org/wiki/faq/pointers-to-members
I believe the correct syntax is:
//std::cout << (bar.*fn_ptr)(1) << std::endl;
std::cout << (bar.*(bar.fn_ptr))(1) << std::endl;
I have encountered the following strange situation: I have managed to have a global static variable with two instances ... Is this normal or is this a bug in the compiler or is this a hidden realm of C++? The following reproduction is an extract from a larger project (where the behaviour is the same), obviously the names were changed to protect the culprit (and yes, I know there are memory leaks in this code).
Here comes the code:
// other.h
#ifndef _OTHER_H_
#define _OTHER_H_
struct other
{
long longer;
int inter;
char charer;
};
void dosomething();
#endif
And
// other.cpp
#include "other.h"
#include "util.h"
void dosomething()
{
other* something = alloc_mem(other, 4);
}
And
// util.h
#ifndef _UTIL_H_
#define _UTIL_H_
#include <memory.h>
#include <string>
#include "test_class.h"
template <class T> T* allocate(size_t count, const char* f, long l, const char* sth)
{
T* tmp = new T[count];
memset(tmp, 0, count * sizeof(T));
test_class<T*>::instance().throwIn(tmp, f, l, sth, count);
return tmp;
}
#define alloc_mem(type,count) allocate<type>(count, __FILE__, __LINE__, (char*)0)
#endif
And
// main.cpp
#include "other.h"
#include "util.h"
int main()
{
int* i = alloc_mem(int, 1);
int* i1 = alloc_mem(int, 20);
char* c = alloc_mem(char, 1);
dosomething();
int* i3 = alloc_mem(int, 1);
}
And the main part:
// test_class.h
#ifndef test_class_H
#define test_class_H
#include <stdlib.h>
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
static long int all_alloc = 0; // THIS will get linked in two times!
template <typename T>
class test_class
{
private:
test_class() {}
static test_class<T>* pinstance;
public:
~test_class() {}
static test_class& instance() {
if(pinstance == NULL) {
pinstance = new test_class();
}
return *pinstance;
}
void throwIn(T item, const char* file, long line, const char* _compiler, long count) {
int status;
char* s = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status) ;
std::cout << "request:" << sizeof(T) * count << " bytes, type:" << s << " # "<<
file << ":" << line << " global_addr:" << &all_alloc << std::endl;
all_alloc += sizeof(T) * count ;
free(s);
std::cout<<"All memory:" << all_alloc << std::endl;
}
};
template <class T> test_class<T>* test_class<T>::pinstance = NULL;
#endif
So, you have to compile this as:
g++ main.cpp other.cpp -o test
and the run it, and:
$ ./test
request:8 bytes, type:int* # main.cpp:6 global_addr:0x6022d8
All memory:8
request:160 bytes, type:int* # main.cpp:7 global_addr:0x6022d8
All memory:168
request:8 bytes, type:char* # main.cpp:8 global_addr:0x6022d8
All memory:176
request:32 bytes, type:other* # other.cpp:6 global_addr:0x6022f8
All memory:32
request:8 bytes, type:int* # main.cpp:11 global_addr:0x6022d8
All memory:184
so, as I could see with a pretty big surprise, I have two global addresses for all_alloc... Indeed, nm -C test shows:
00000000006022d8 b all_alloc
00000000006022f8 b all_alloc
So, obviously the questions:
Why? How is this possible? Is there something allowing this kind of behaviour or is this a bug somewhere in the compiler or linker?
In this case, I don't think you want to declare your all_alloc static. In this case, it means that the linkage is internal. In your case, you get two copies since two files include the header.
If you remove static, then you will have two copies that clash, and result in a linker error. Which is not good.
I believe what you want to do is to change static to extern, then in one cpp file, define the variable and its value.
header:
extern long int all_alloc;
cpp:
long int all_alloc = 0;
This will provide one copy of all_alloc that is shared among your code.
When you have global variable it already has static duration, so static keyword means something different for it. As you have class definition in the file you define your global static variable I assume that is a header. Why it is bad idea to use static global variable in header and what you will get you can read here
So answer is: it is expected behavior and not a bug.
I'm getting a runtime error ("memory can't be written") that, after inspection through the debugger, leads to the warning in the tittle.
The headers are the following:
componente.h:
#ifndef COMPONENTE_H
#define COMPONENTE_H
using namespace std;
class componente
{
int num_piezas;
int codigo;
char* proovedor;
public:
componente();
componente(int a, int b, const char* c);
virtual ~componente();
virtual void print();
};
#endif // COMPONENTE_H
complement.h implementation
#include "Componente.h"
#include <string.h>
#include <iostream>
componente::componente()
{
num_piezas = 0;
codigo = 0;
strcpy(proovedor, "");
//ctor
}
componente::componente(int a = 0, int b = 0, const char* c = "")
{
num_piezas = a;
codigo = b;
strcpy(proovedor, "");
}
componente::~componente()
{
delete proovedor;//dtor
}
void componente::print()
{
cout << "Proovedor: " << proovedor << endl;
cout << "Piezas: " << num_piezas << endl;
cout << "Codigo: " << codigo << endl;
}
teclado.h
#ifndef TECLADO_H
#define TECLADO_H
#include "Componente.h"
class teclado : public componente
{
int teclas;
public:
teclado();
teclado(int a, int b, int c, char* d);
virtual ~teclado();
void print();
};
#endif // TECLADO_H
teclado.h implementation
#include "teclado.h"
#include <iostream>
teclado::teclado() : componente()
{
teclas = 0;//ctor
}
teclado::~teclado()
{
teclas = 0;//dtor
}
teclado::teclado(int a = 0, int b = 0, int c = 0, char* d = "") : componente(a,b,d)
{
teclas = c;
}
void teclado::print()
{
cout << "Teclas: " << teclas << endl;
}
The main method where I get the runtime error is the following:
#include <iostream>
#include "teclado.h"
using namespace std;
int main()
{
componente a; // here I have the breakpoint where I check this warning
a.print();
return 0;
}
BUT, if instead of creating an "componente" object, I create a "teclado" object, I don't get the runtime error. I STILL get the warning during debugging, but the program behaves as expected:
#include <iostream>
#include "teclado.h"
using namespace std;
int main()
{
teclado a;
a.print();
return 0;
}
This returns "Teclas = 0" plus the "Press any key..." thing.
Do you have any idea why the linker is having troube with this? It doesn't show up when I invoke the virtual function, but before, during construction.
Two errors that I can see:
strcpy(proovedor, ""); // No memory has been allocated to `proovedor` and
// it is uninitialised.
As it is uninitialised this could be overwriting anywhere in the process memory, so could be corrupting the virtual table.
You could change this to (in both constructors):
proovedor = strdup("");
Destructor uses incorrect delete on proovedor:
delete proovedor; // should be delete[] proovedor
As this is C++ you should considering using std::string instead of char*.
If you do not change to std::string then you need to either:
Implement a copy constructor and assignment operator as the default versions are incorrect if you have a member variable that is dynamically allocated, or
Make the copy constructor and assignment operator private to make it impossible for them to be used.
Another source of this same message is that gdb can get confused by not-yet-initialized variables. (This answers the question title, but not the OP's question, since a web search led me here looking for an answer.)
Naturally, you shouldn't have uninitialized variables, but in my case gdb attempts to show function local variables even before they are declared/initialized.
Today I'm stepping through another developer's gtest case and this message was getting dumped to output every time the debugger stopped. In this case, the variable in question was declared on ~line 245, but the function started on ~line 202. Every time I stopped the debugger between these lines, I received the message.
I worked around the issue by moving the variable declaration to the top of the function.
For reference, I am testing with gdb version 7.11.1 in QtCreator 4.1.0 and I compiled with g++ version 5.4.1