offsetof() of nested C struct in C++ - c++

I'm trying to add a socket filter to one of my sockets in C++ (Linux). In the socket filter I need to get the offset of struct fork_proc_event, which is nested within another structure. The definition looks like this (cn_proc.h):
struct proc_event {
...
union {
...
struct fork_proc_event {
__kernel_pid_t parent_pid;
...
} fork;
...
} event_data;
...
};
In C I would do this:
int off = offsetof(struct fork_proc_event, parent_pid);
However I'm developing in C++. If I try to do this:
int off = offsetof(proc_event::fork_proc_event, parent_pid);
I get the following error:
error: expected type-specifier
error: expected `,'
error: expected `)' before ',' token
How should the offsetof() line look like?

It may help to think of how an implementation of an offsetof macro might go. Here's one example:
#define offsetof(TYPE, MEMBER) \
((uintptr_t)&(((TYPE*)0)->MEMBER))
In other words, using 0 as a pointer to the type you're interested in, and simply taking the address of the struct field...
So if you wanted the offset of parent_pid relative to fork (which is how I initially parsed your question):
((char*)&((struct proc_event*)0)->event_data.fork.parent_pid) - ((char*)&((struct proc_event*)0)->event_data.fork)
On second reading it sounds like you might just want the offset of parent_pid relative to the start of struct proc_event. Adapting the example above that would be:
((uintptr_t)&((struct proc_event*)0)->event_data.fork.parent_pid)

I don't exactly understand the need for all those hacks, when all you have to do is give a name to your nested union type. Any name, just to be able to refer to it in C++ code
struct proc_event {
...
union whatever {
...
struct fork_proc_event {
__kernel_pid_t parent_pid;
...
} fork;
...
} event_data;
...
};
Then you'll be able to refer to it as proc_event::whatever::fork_proc_event in offsetof in C++ code
size_t off = offsetof(proc_event::whatever::fork_proc_event, parent_pid);
If you are interested in offset of parent_pid from the beginning of proc_event, you can do
size_t off = offsetof(proc_event, event_data.fork.parent_pid);
If you cannot change the declaration, you can calculate the offset of parent_pid inside fork_proc_event by doing
size_t off =
offsetof(proc_event, event_data.fork.parent_pid) -
offsetof(proc_event, event_data.fork);
(Although I can't say right away whether the last two are formally legal examples of offsetof usage, they will normally work in practice without any problems.)

Related

Default value for template constant in C++

I'm trying to replace a global buffer size to one that can be modifiable for tests. The current code is something like:
static const uint32_t BUFFER_SIZE = 1 << 8;
class BufferWrapper {
.
.
.
char buffer_[BUFFER_SIZE];
};
This causes a problem when I'm trying to change the BUFFER_SIZE for tests. Thus, I was hoping to make the BUFFER_SIZE a template constant, and having a default value for said constant so that I only need to specify it during tests, something like:
static const uint32_t BUFFER_SIZE = 1 << 8;
template <uint_32 SIZE = BUFFER_SIZE>
class BufferWrapper {
.
.
.
char buffer_[SIZE];
};
That way, previous declarations can still compile like:
BufferWrapper buf
But during a test, I could write something like this to test a buffer of 1KB:
BufferWrapper<1024> test_buf;
My question is, is it possible to provide a default for a template value, and how would I do it? The error I get with the above when I declare something like BufferWrapper buf; is:
error: use of class template 'BufferWrapper' requires template arguments; argument deduction not allowed in function prototype
There is no problem with the shown program in C++17.
Prior to C++17, you must provide the template argument list even if it is empty:
BufferWrapper<> test_buf;
In such case you can avoid changing the client code by using a type alias:
template <uint_32 SIZE = BUFFER_SIZE>
class BufferWrapperTemplate;
using BufferWrapper = BufferWrapperTemplate<>;
As this answer states, the code is fine since C++17. However, if you do not have access to that, you can still get around the need to change all existing code to use BufferWrapper<> instead of BufferWrapper.
Do this by renaming BufferWrapper to something else (e.g. BufferWrapperTemplate) and providing a type alias to the default-sized version:
template <uint_32 SIZE = BUFFER_SIZE>
class BufferWrapperTemplate {
.
.
.
char buffer_[SIZE];
};
typedef BufferWrapperTemplate<> BufferWrapper;
This way, all existing code can keep using BufferWrapper, and tests can use BufferWrapperTemplate<42> where needed.

C++ - What do these lines of code mean?

I'm looking at some source code and don't understand what is going on. Here is some code I've put together from that source code (definitions came from all over the place and I've included only what's necessary):
#define TOC 0x1C75288
typedef unsigned int uint32_t;
typedef unsigned int uint;
struct opd_s
{
uint32_t Sub;
uint32_t Toc;
};
namespace Offsets{
enum Address{
GET_PLAYER_NAME = 0x421974
};
}
opd_s GET_PLAYER_NAME_t = { Offsets::GET_PLAYER_NAME, TOC };
char*(*GET_PLAYER_NAME)(uint PlayerID) = (char*(*)(uint))&GET_PLAYER_NAME_t;
Specifically, what do these last 2 lines mean and do? :
opd_s GET_PLAYER_NAME_t = { Offsets::GET_PLAYER_NAME, TOC };
char*(*GET_PLAYER_NAME)(uint PlayerID) = (char*(*)(uint))&GET_PLAYER_NAME_t;
Later in the source code I see a usage of GET_PLAYER_NAME and it looks like this:
char* player = GET_PLAYER_NAME(0);
So is GET_PLAYER_NAME some sort of a function that takes an argument of an integer?
I'm just really confused about this and am trying to understand it, so if someone could exaplain the meaning and syntax, that would be extremely helpful. Thanks!
opd_s GET_PLAYER_NAME_t = { Offsets::GET_PLAYER_NAME, TOC };
means create struct variable on stack with name GET_PLAYER_NAME_t of type opd_s and initialize it with fields Sub = Offsets::GET_PLAYER_NAME, i.e. 0x421974 and Toc = TOC, i.e. 0x1C75288.
So, there is a struct named GET_PLAYER_NAME_t with opd_s type, which is equal to { 0x421974, 0x1C75288 }.
char*(*GET_PLAYER_NAME)(uint PlayerID) = (char*(*)(uint))&GET_PLAYER_NAME_t;
It defines function pointer GET_PLAYER_NAME(uint PlayerID) which is pointed to former declared struct.
Actually GET_PLAYER_NAME(0) calls something with op-codes 0x421974, 0x1C75288, which we cannot know what it does, because we don't know the architecture it is compiled for (at least bitness and endianness of the architecture).
Surely it's not x86, DEP on x86 blocks executing stack data as code.
opd_s GET_PLAYER_NAME_t = { Offsets::GET_PLAYER_NAME, TOC };
This declares a variable named GET_PLAYER_NAME_t of type opd_s. This is initialized to { Offsets::GET_PLAYER_NAME, TOC } i.e. the Sub data member will be Offsets::GET_PLAYER_NAME and the Toc data member will be TOC.
char*(*GET_PLAYER_NAME)(uint PlayerID) = ...
This declares a variable named GET_PLAYER_NAME. Its type is: pointer to a function taking an uint as argument and returning `char *.
(char*(*)(uint))&GET_PLAYER_NAME_t;
This casts the adress of GET_PLAYER_NAME_t to a pointer ... see above.
This looks very suspicious as the contents of the GET_PLAYER_NAME_t variable which is a struct will be interpreted as the first instruction(s) in a function call via GET_PLAYER_NAME.
This is how functions are called on PS3 via a prx module. This code runs on an external plugin know as a prx module. Think of it kind of like a DLL. You can load the game's executable into IDA and get the address of the function you want to call. So in this case, 0x421974 is being called. Since we don't actually have the game's source, you need to define the function like this:
char*(*GET_PLAYER_NAME)(uint PlayerID) = (char*(*)(uint))&GET_PLAYER_NAME_t;
The opd structure is just an int array which is specific to the cell processor.
On Xbox it would just be like this:
char*(*GET_PLAYER_NAME)(uint PlayerID) = (char*(*)(uint))0x421974;
Pretty much all it does is call 0x421974 which is GET_PLAYER_NAME on GTA5 and gets a players name from their client index.
The processor is powerpc.

Why doesn't C++ allow const after ::?

Folks,
Problem Statement - Does C++ allow a (static) const be limited to a class scope, so I can get rid of #defines that pollute entire namespace?
My observation is NO (in the following DIFFERENT examples), and I'd like to find out why and what's the best alternative. VS generates error C2589: 'const' : illegal token on right side of '::'
EXAMPLE1
// a.h
class A
{
…
..
static const uint_32 myConst = 1234;
};
//b.cpp
include “a.h”
…
B()
{
uint32_t arr[A::myConst]; // C2589! const : illegal token on right side of '::'
}
EXAMPLE 2
// a.h
class A
{
…
..
enum blah
{
...
myConst = 1234,
..
};
};
//b.cpp
include “a.h”
...
B()
{
uint32_t arr[A::myConst]; // C2589! const : illegal token on right side of '::'
}
When you take your macro:
#define CONST 1234
and substitute it for where you use it:
static const int CONST = 1234;
The end result is nonsense:
static const int 1234 = 1234;
In another instance:
Int a1[a::CONST];
This also becomes nonsense:
Int a1[a::1234];
This all begs the question, what are you trying to do?
It looks like you're trying to create a member variable with the same name as your macro, CONST, here:
class A
{
static const int CONST = 1234;
};
However since when this code is compiled the macro has already been defined, the preprocessor changes this by substituting the macro before the compiler itself can get a crack at it. By the time the code is compiled, it looks like this:
class A
{
static const int 1234 = 1234;
};
Best is to just do away with the macro entirely, and then retrofit your code to use proper constants like you're trying to do here. Don't mix and match. At the very least, don't use the same name for the member as you do for the macro.
First of all your class is called A, as in capital A, not a. The class name is used to qualify the constant you are trying to use. So, change your code to use A::CONST. By the way, this is C++ not C# or Java, so there is no such thing as an Int, unless for some bizarre reason you decided to invent your own integer type.
As an aside, using all caps to name constants can collide with macros and is a good way to get into trouble, especially since pre-processing happens first and macros are substituted for all cases of the constants. This can often lead to invalid C++ code with syntax errors that are difficult to understand. That's why you should never use all caps to name constants, since this is a convention most commonly used for macros.
If I may make a guess, it looks like you're trying to use :: the same way you use . in Python.
It looks like you really don't understand what the scope resolution operator does, or how it works.
:: has a very specific, and quite limited usage. Until you understand it better, we're going to have a really hard time helping you.

Insufficient contextual information to determine type

I've done research and I can't make sense of this message at all. Everything I find seems to be a bug with the compiler itself. I've also read somewhere 'insufficient contextual information to determine type' is not a helpful message.
My question: Does anyone have information on what this compile error message means?
I understand this question might be code specific. My code merely declares a global anonymous struct, and then once it tries to access it in a function I get this error (or so I've evaluated it).
EDIT: I got my code to compile! - But I still don't know what the error means, so I'll leave the question open.
EDIT: Here's my code, as far as I'd suppose is important:
typedef ofstream::pos_type ofilepos;
struct stack // stack is my own stack data-structure
{
// ...
// int L; struct N *l;
stack(): L(0), l(NULL) {}
}
// ...
struct
{
const char* zero;
stack<ofilepos> chunks; // it was 'chunks();' with (), and it didn't work
} _fileext = {"\0\0\0"};
// ...
ofstream& write_stack_pushsize(ofstream& f)
{
_fileext.chunks.push(new ofilepos(f.tellp()));
f.write(_fileext.zero,4);
return f;
}
I think it might have been because I was calling a constructor in a struct declaration, rather than later... or something... it could be a bug in C++03.
Regarding this code,
struct
{
const char* zero;
stack<ofilepos> chunks();
} _fileext = {"\0\0\0"};
there is no way to provide a definition of the chunks member function after the anonymous struct definition.
Considering also the following usage example,
ofstream& write_stack_pushsize(ofstream& f)
{
_fileext.chunks.push(new ofilepos(f.tellp()));
f.write(_fileext.zero,4);
return f;
}
apparently you meant to define chunks as a data member instead of as a function member.
By the way, using underscore at the start of a name can possibly conflict with names in the implementation of the standard library. E.g. these names are reserved in the global namespace (if I recall correctly). The usual convention is instead to have an underscore at the end of a name, to signify "member".
To signyfy "global" I simply use a namespace that I call g. :-)

Would the following code causing problems in C++?

I saw someone writing code like this , in a C++ class:
int foo ( int dummy )
{
this->dummy = dummy;
}
Shall we use code like that , will it cause problems ?
I tried to compile something like this , it seems to be worked.
#update:
I posted this mostly about the name dummy , and the internal variable this->dummy , and if it's problem causing
That's perfectly fine for a member function, other than you're missing a return statement. dummy will shadow the member variable and so you use this-> to refer to member.
int foo ( int dummy )
{
this->dummy = dummy; // set member to argument
return this->dummy;
}
Don't do this for things more complex than a simple set function, as it's confusing.
int foo ( int dummy ) // Bad practise! Rename this param as the function isn't a setter
{
this->dummy = dummy * 2 + 1;
return this->dummy;
}
There is nothing wrong with doing that perse. It can get confusing though if you use dummy assuming it is coming from the class but its actually coming from the parameter.
IMO, its better to use something to denote it is a class member. Some people use simply mDummy, other m_Dummy, others just write dummy_.
Its up to you what you prefer but most of all you should be consistent.
The code is not fine. The function is defined as returning an int but there is no return statement. The compiler might only give a warning about this, but the function calling foo might expect it to return a valid value, which it doesn't, and bad stuff might happen.
You have to do it this way if you're passing a parameter with the same name as the member variable.
But it might be a better practice to avoid a hidden (member-)variable by using different names. There's different coding styles, some would use dummy_, some would use mDummy or other ways to name member variables. This makes your code less confusing.
Well there is nothing wrong with your use, but the code needs to return an int as its an int function :)
Dummy variable in your current class is assigned to the passed int, however do remember they are different but now pointing to the same thing, therefore its better to give it a different name as its in a different.
You could however loose precision under certain variable types.
#include <stddef.h>
typedef struct intlist {
int size;
int i[1];
} intlist;
intlist *
makeintlist (int size)
{
intlist *ilp = malloc (offsetof (intlist, i[size])); /* not C++ */
ilp->size = size;
return ilp;
}
member variable size is allocated to size
That will work.
Don't do it, it's confusing!