I am trying to compile QT5.3
The files in question are qv4executableallocator_p.h and qv4executableallocator.cpp. Relevant code snippet from the header is below
struct Allocation{
Allocation()
: addr(0)
, size(0)
, free(true)
, next(0)
, prev(0)
{}
void *start() const;
void invalidate() { addr = 0; }
bool isValid() const { return addr != 0; }
void deallocate(ExecutableAllocator *allocator);
private:
~Allocation() {}
friend class ExecutableAllocator;
Allocation *split(size_t dividingSize);
bool mergeNext(ExecutableAllocator *allocator);
bool mergePrevious(ExecutableAllocator *allocator);
quintptr addr;
uint size : 31; // More than 2GB of function code? nah :)
uint free : 1;
Allocation *next;
Allocation *prev;
};
In the cpp function ExecutableAllocator::ChunkOfPages::~ChunkOfPages() I get a compilation error when trying to access alloc->next.
QV4::ExecutableAllocator::Allocation* QV4::ExecutableAllocator::Allocation::next’ is private
Code can be seen online at https://qt.gitorious.org/qt/qtdeclarative/source/be6c91acc3ee5ebb8336b9e79df195662ac11788:src/qml/jsruntime
My gcc version is relatively old... 4.1
Is this the issue or is something else wrong in my environment. I would like a way to go forward. I am stuck with this compiler, since it is the one I have to use on my target platform
I'd guess that the QV4::ExecutableAllocator::ChunkOfPages struct is not directly befriended with Allocation, so you can't access Allocation's private data in its destructor in C++ prior to C++11 standard.
Try adding friend struct ExecutableAllocator::ChunkOfPages to the Allocation definition, that should do the trick.
There was a slight change in the way nested classes are handled in C++11 (cited from cppreference.com):
Prior C++11, member declarations and definitions inside the nested class of the friend of class T cannot access the private and protected members of class T, but some compilers accept it even in pre-C++11 mode.
Which could explain why this worked in a new compiler, but not in your old one.
Related
In embedded systems, you often have a memory location which is not within the program memory itself but which points to some hardware registers. Most C SDKs provide these as #define statements. According to the following article, https://arne-mertz.de/2017/06/stepping-away-from-define/ one method of transitioning from #define statements (as used by C SDKs) to something more C++ friendly, is to create a class which forces reinterpret_cast to occur at runtime.
I am trying to go about this in a slightly different way because I want to be able to create "type traits" for the different pointers. Let me illustrate with an example.
#define USART1_ADDR 0x1234
#define USART2_ADDR 0x5678
template <typename T_, std::intptr_t ADDR_>
class MemPointer {
public:
static T_& ref() { return *reinterpret_cast<T_*>(ADDR_); }
};
class USART {
public:
void foo() { _registerA = 0x10; }
private:
uint32_t _registerA;
uint32_t _registerB;
};
using USART1 = MemPointer<USART, USART1_ADDR>;
using USART2 = MemPointer<USART, USART2_ADDR>;
template <typename USART_>
class usart_name;
template <>
class usart_name<USART1> {
public:
static constexpr const char* name() { return "USART1"; }
};
template <>
class usart_name<USART2> {
public:
static constexpr const char* name() { return "USART2"; }
};
Each USART "instance" in this example is its own, unique type so that I am able to create traits which allow compile-time "lookup" of information about the USART instance.
This actually seems to work, however, I wanted to create some test code as follows
static USART testUsart;
#define TEST_USART_ADDR (std::intptr_t)(&testUsart);
using TEST_USART = MemPointer<USART, TEST_USART_ADDR>;
Which fails with the following error:
conversion from pointer type 'USART*' to arithmetic type
'intptr_t' {aka 'long long int'} in a constant expression
I believe I understand the source of the problem based upon Why is reinterpret_cast not constexpr?
My question is, is there a way to make my MemPointer template work for test code like above as well?
EDIT
One solution is to have a separate class for each "instance" has follows
class USART1 : public USART {
public:
static USART& ref() { return *reinterpret_cast<USART*>(USART1_ADDR); }
};
class USART2 : public USART {
public:
static USART& ref() { return *reinterpret_cast<USART*>(USART2_ADDR); }
};
I would prefer some sort of template + using combination though so that I don't need to write a bunch of classes. But perhaps this is the only option.
is there a way to make my MemPointer template work for test code like above as well?
You could just stop insisting that the address be an intptr_t. You're going to cast it to a pointer anyway, so why not just allow any type for which that conversion exists?
template <typename T_, typename P, P ADDR_>
class MemPointer {
public:
static T_& ref() { return *reinterpret_cast<T_*>(ADDR_); }
};
using USART1 = MemPointer<USART, std::intptr_t, USART1_ADDR>;
using USART2 = MemPointer<USART, std::intptr_t, USART2_ADDR>;
static USART testUsart;
using TEST_USART = MemPointer<USART, USART*, &testUsart>;
Follow-up notes:
if this were for a library to be used by others, I'd consider adding a static_assert(std::is_trivial_v<T_>) inside MemPointer to catch annoying errors
there are a few potential issues around things like padding & alignment, but I assume you know what your particular embedded platform is doing
you should volatile-qualify your register members, or the whole object (eg. you can return std::add_volatile_t<T_>& from MemPointer::ref)
This is so the compiler knows that every write is an observable side-effect (ie, observable by the hardware even if your program never reads it back), and that every read may produce a different value (because the hardware can update it even if your program doesn't).
I use a SFML library for graphics and other stuff,such as vectors. In my Brain class I try to do something like:
class Brain{
Brain(int size){
Vector2f directions[size];
}
}
But it throws an error saying it must evaluate to a constant. I tried all sorts of things but I can't get it to compile properly. Anyone knows why this happens and how can I fix it?
As suggested in the comments in C++ the size of an array must be known at compile time... if you need dynamic containers you can use std::vector.
class Brain {
public:
Brain(int size) : _directions{size}
{
}
private:
vector<Vector2d> _directions;
};
Don't forget public and private access to your class... By default everything is private on a class so in your snippet the contructor of the class is private!
I inherited some 10 year old code I have to complete. The code is in MFC (C++).
There's a .h file where the custom data structures are written and some const variables are in there as Globals. Some of these are used for MS Office file extensions, of type CString, and are declared as _T(".doc"), _T(".xls"), etc.
Obviously these are dated and need to be updated to recognize the Office 2007 and later extensions. My first brilliant idea was to use const_cast to change the constant if needed, but found out later that's a no-no and resulted in undefined behavior (sometimes it would switch back to .doc).
I then decided to create a struct and have two structs inherit from it. I created a void method in the base struct to make it abstract but otherwise it does nothing. Here's the code:
struct eOfficeExtensions{
const CString WORD_EXTENSION;
const CString EXCEL_EXTENSION;
const CString WORDPAD_EXTENSION;
const INT EXTENSION2007;
eOfficeExtensions(CString word, CString excel, CString wordpad, INT ver) :
WORD_EXTENSION(word), EXCEL_EXTENSION(excel), WORDPAD_EXTENSION(wordpad), EXTENSION2007(ver){}
//method to ensure base class is abstract
virtual void Interface() = 0;
};
struct eOfficeExtensions2003 : public eOfficeExtensions{
public:
eOfficeExtensions2003() : eOfficeExtensions(_T(".doc"), _T(".xls"), _T(".rtf"), 0){}
private:
virtual void Interface(){}
};
struct eOfficeExtensions2007OrLater : public eOfficeExtensions{
eOfficeExtensions2007OrLater() : eOfficeExtensions(_T(".docx"), _T(".xlsx"), _T(".rtf"), 1){}
private:
virtual void Interface(){}
};
This feels like a ridiculous amount of code for what should be a simple conditional definition. What would an experienced programmer do?
EDIT
These constants should only be set once and never changed. The version of MS Office installed is determined by scanning registry subkeys in a class that deals with memory management.
The constants are mainly used to create new files or search a directory for files with that extension, not for resolving conditional statements. The struct should also be instantiated once as a eOfficeExtensions* pointer to the relevant child struct.
Your inheritance tree essentially defines two different values for the base struct.
You don't need inheritance just to define those values, you only need two variables:
struct eOfficeExtensions{
const CString WORD_EXTENSION;
const CString EXCEL_EXTENSION;
const CString WORDPAD_EXTENSION;
const INT EXTENSION2007;
};
const eOfficeExtensions extensions2003{_T(".doc"), _T(".xls"), _T(".rtf"), 0};
const eOfficeExtensions extensions2007{_T(".docx"), _T(".xlsx"), _T(".rtf"), 1};
const eOfficeExtensions* extensions = 0;
// ... Later ...
if (office2007Installed)
extensions = &extensions2007;
else
extensions = &extensions2003;
I have a library that is all tested thoroughly through google test suite. I am trying to keep it "pimpl" clean, but I'm running into a segfault I can't quite figure out.
Relevant Code:
Interface.h:
class Interface{
public:
Interface();
void Function(const int argument);
private:
std::unique_ptr<Implementation> Implement;
std::unique_ptr<DependencyInjection> Injection1, Injection2;
};
Interface.cpp:
Interface::Interface()
: Injection1(new DependencyInjection()),
Injection2(new DependencyInjection()),
Implement(new Implementation(*Injection1, *Injection2)) {}
void Interface::Function(const int argument){ Implement->Function(argument); }
Implementation.h:
class Implementation{
public:
Implementation(AbstractInjection &injection1, AbstractInjection &injection2);
void Function(const int argument);
private:
AbstractInjection Injection1, Injection2;
};
Implementation.cpp
Implementation::Implementation(AbstractInjection &injection1, AbstractInjection &injection2)
: Injection1(injection1),
Injection2(injection2) {}
void Implementation::Function(const int argument){
injection1.Function(argument); } // code from here out is all well tested and works
So when I create the interface and call Interface.Function() the code segfaults when it tries to evaluate Implementation.Function(). I've ran gdb through everything I can think of, all the pointers are non-null.
If I just create a test that looks like
std::unique_ptr<DependencyInjection1> injection1(new DependencyInjection());
std::unique_ptr<DependencyInjection2> injection2(new DependencyInjection());
std::unique_ptr<Implementation> implement(new Implementation(*injection1, *injection2));
implement->Function(0);
The code works fine and does not segfault
But if I create a test like
Interface iface;
iface.Function(0);
it will segfault.
I am new to the whole unique_ptr thing, but I have a suspicion that isn't the larger problem. It may be a red herring, I don't know.
The problem should actually pop as as a warning.
Initializers are done in the order in which they appear in the class definition, not in which they appear in the constructor!
Switch it to:
class Interface{
public:
Interface();
void Function(const int argument);
private:
std::unique_ptr<DependencyInjection> Injection1, Injection2;
std::unique_ptr<Implementation> Implement;
};
From here: C++: Initialization Order of Class Data Members, this is "12.6.2 of the C++ Standard"
You've got a wrong order of member fields, they are initialized in order they are declared in the class. So implement is initialized before both injections. Use -Werror=reorder to get compiler error (for GCC and probably CLang)
I'm trying to define a public struct inside a C++ class, and can't figure out how to make it compile. In my header, I have the following:
class AtomUtility
{
public:
struct BoundingBox;
void doWork(struct AtomUtility::BoundingBox bounds);
};
And in the source:
#include"AtomUtility.h"
struct AtomUtility::BoundingBox
{
double xMin, xMax;
};
int main()
{
AtomUtility::BoundingBox *myBox = new AtomUtility::BoundingBox;
myBox->xMin = 0;
myBox->xMax = 10;
AtomUtility *myUtility = new AtomUtility;
myUtility->doWork(*myBox);
delete myUtility;
}
void AtomUtility::doWork(struct AtomUtilty::BoundingBox bounds)
{
//do things...
}
When I attempt to compile this, I get an error: "class "AtomUtility" has no tag member named "BoundingBox".
You've missed the semi-colon after the definition of AtomUtility::BoundingBox and your compiler is getting confused and giving a poor diagnostic.
You're also trying to pass a AtomUtility::BoundingBox* to a function expecting a AtomUtility::BoundingBox
If your compiler gives poor diagnostics it's often useful to try your code on a different compiler. Several are available online, e.g. Comeau, Clang, or a pastebin that compiles, such as http://codepad.org
Quoting https://stackoverflow.com/a/6368118/1483826:
you can only declare pointer or reference to the later class (...). You cannot have objects of later class.
To fix this, you'd need to declare the struct before the class using it as a field.