Forum: PC-Programmierung vector -> void* -> vector erlaubt?


von cppbert (Gast)


Lesenswert?

Ich wurde von einem Kumpel (der hat angefangen irgendwas mit 
Cyper-Security zu studieren) gefragt ob solche casts durch den Standard 
supported werden oder ob man da durch in irgenwelche Alignment, UB 
Verhalten rennen kann

Ich habe nichts dazu gefunden und sehe das als hässlich aber 
unproblematisch an

man muss nur aufpassen das der vector nicht über verschiedene Heaps oder 
Debug/Release-Grenzen durchgereicht werden darf
1
#include <vector>
2
3
struct test
4
{
5
    double x;
6
};
7
8
int main()
9
{
10
    std::vector<test> tests{{10.0},{20.0}};
11
    
12
    void* a = reinterpret_cast<void*>(&tests);
13
    std::vector<test>* a2 = reinterpret_cast<std::vector<test>*>(a);
14
    a2->push_back({30.0});
15
16
    void* b = reinterpret_cast<void*>(&tests[0]);
17
    test* b2 = reinterpret_cast<test*>(b);
18
    *b2 = {40.0};
19
}

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Ganz heißer Tipp für den Cyber-Security Kumpel. Wenn er in seinem Beruf 
später was werden will, statt nur den Cyber-Clown mit Wikipedia-Wissen 
abzugeben, dann sollte er sich sehr früh (also jetzt) daran machen 
Fakten selber zu recherchieren. Das heißt an die Quelle gehen und, auch 
wenn es weh tut, ekelhafte Standard-Dokumente durchackern. Wie gesagt, 
selber!

von mh (Gast)


Lesenswert?

cppbert schrieb:
> Ich habe nichts dazu gefunden und sehe das als hässlich aber
> unproblematisch an

Dann solltest du das Suchen nochmal üben. Im Standard zum 
reinterpret_cast (http://eel.is/c++draft/expr.reinterpret.cast#7):
1
An object pointer can be explicitly converted to an object pointer of a different type.64 When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is static_­cast<cv T*>(static_­cast<cv void*>(v)). [ Note: Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. — end note ]

von cppbert (Gast)


Lesenswert?

mh schrieb:
> cppbert schrieb:
>> Ich habe nichts dazu gefunden und sehe das als hässlich aber
>> unproblematisch an
>
> Dann solltest du das Suchen nochmal üben. Im Standard zum
> reinterpret_cast (http://eel.is/c++draft/expr.reinterpret.cast#7):
> An object pointer can be explicitly converted to an object pointer of a
> different type.64 When a prvalue v of object pointer type is converted
> to the object pointer type “pointer to cv T”, the result is
> static_­cast<cv T*>(static_­cast<cv void*>(v)). [ Note: Converting a
> prvalue of type “pointer to T1” to the type “pointer to T2” (where T1
> and T2 are object types and where the alignment requirements of T2 are
> no stricter than those of T1) and back to its original type yields the
> original pointer value. — end note ]

Ich hab nichts "Gegenteiliges" dazu gefunden...

von Rolf M. (rmagnus)


Lesenswert?

cppbert schrieb:
> Ich hab nichts "Gegenteiliges" dazu gefunden...

Das wäre ja auch verwunderlich. Warum sollte sich der Standard selbst 
widersprechen?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

cppbert schrieb:
> ... Cyper-Security ...
> vector -> void* -> vector erlaubt?

Der gezeigte Code castet nicht Objekte zu void*, sondern Zeiger auf 
strd::vector<test>:
1
std::vector<test>* -> void* -> std::vector<test>*
also
1
vector* -> void* -> vector*
bzw.
1
test* -> void* -> test*
und nicht

> vector -> void* -> vector erlaubt?

von cppbert (Gast)


Lesenswert?

Johann L. schrieb:
> cppbert schrieb:
>> ... Cyper-Security ...
>> vector -> void* -> vector erlaubt?
>
> Der gezeigte Code castet nicht Objekte zu void*, sondern Zeiger auf
> strd::vector<test>:
> std::vector<test>* -> void* -> std::vector<test>*alsovector* -> void* ->
> vector*bzw.test* -> void* -> test*und nicht
>
>> vector -> void* -> vector erlaubt?

Fehler im Betreff, meinte natürlich alles mit Pointer, so wie im 
Beispiel-Code

von Carl D. (jcw2)


Lesenswert?

cppbert schrieb:
> Johann L. schrieb:
>> cppbert schrieb:
>>> ... Cyper-Security ...
>>> vector -> void* -> vector erlaubt?
>>
>> Der gezeigte Code castet nicht Objekte zu void*, sondern Zeiger auf
>> strd::vector<test>:
>> std::vector<test>* -> void* -> std::vector<test>*alsovector* -> void* ->
>> vector*bzw.test* -> void* -> test*und nicht
>>
>>> vector -> void* -> vector erlaubt?
>
> Fehler im Betreff, meinte natürlich alles mit Pointer, so wie im
> Beispiel-Code

Also z.B. ein Callback aus einer Lib bekommt einen void* als "User 
Contest" übergeben und der wird aus einem std::vector<>* gefastet. Was 
soll daran nicht funktionieren, außer das der Compiler nicht prüfen 
kann, ob der "back-cast" Typgerecht erfolgt. Das muß der Autor 
sicherstellen. Wobei man sich da was gegen Unachtsamkeit dessen 
einfallen lassen kann.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Ein reinterpret_cast ist übrigens gar nicht nötig. Es ist garantiert, 
dass ein beliebieger Objektzeiger verlustlos ohne Cast in einen void* 
und per static_cast wieder zurück gewandelt werden kann.
Also ginge statt obigem Code auch:
1
#include <vector>
2
3
struct test
4
{
5
    double x;
6
};
7
8
int main()
9
{
10
    std::vector<test> tests{{10.0},{20.0}};
11
12
    void* a = &tests;
13
    std::vector<test>* a2 = static_cast<std::vector<test>*>(a);
14
    a2->push_back({30.0});
15
16
    void* b = &tests[0];
17
    test* b2 = static_cast<test*>(b);
18
    *b2 = {40.0};
19
}

Ein reinterpret_cast dient ja eigentlich dazu, die Bits, aus denen ein 
Objekt aufgebaut ist, als Objekt eines anderen Typ zu interpretieren. 
Bei void* gibt's aber keine Bits zum interpretieren.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.