5

How to use a private member from outside the class

 3 years ago
source link: https://quuxplusone.github.io/blog/2020/12/03/steal-a-private-member/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

How to use a private member from outside the class

Yesterday I asked:

Am I missing some subtle mechanism by which “unused” private members might actually be referenced from other TUs?

Indeed, I was! Check this out (Godbolt):

struct S {
private:
    static int private_static_data;
};
int S::private_static_data = 42;  // Optimize this away?


// Meanwhile, in some other TU...
static int *f();

template<int *x>
struct F {
    friend int *f() { return x; }
};
template struct F<&S::private_static_data>;

int steal_private_data() {
    return *f();
}

According to [temp.spec]/6, the template arguments of explicit instantiation declarations are permitted to name “private types or objects that would normally not be accessible” — such as S::private_static_data in this case.

So we can instantiate F<&S::private_static_data>, even though we cannot actually refer to that instantiation by name afterwards. This “leaks” the private data of S into F. F leaks it out again via the global function f(). And then anyone can call f() to obtain a pointer to S’s private data.

Therefore, although the compiler of TU #1 can see that none of S’s members and friends use S::private_static_data, it cannot conclude that the definition of S::private_static_data is unused. Other object files may indeed refer to that linker symbol. So the compiler must generate code for it.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK