vector -> void* -> vector erlaubt?

Gast #6227465
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
}
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!
Gast
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 ]
Gast
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...
Gast
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
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.
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 6 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.