expertenaustausch > comp.lang.* > comp.lang.iso-c++

Michael Trocken (17.11.2003, 16:48)
Bei der Weiterverwertung von in C geschriebenem Quell-Kode stößt man
auf das Problem, dass in C++ - im Unterschied zu C - ein Cast auf das
Ergebnis von malloc erforderlich ist.

Dies liegt daran, dass man in C++ einen void* nicht einem anderen
Zeiger zuweisen darf. Beispiel:

char* str = malloc(10); // Fehler in C++

Ich habe mir Folgendes ausgedacht, um malloc dennoch gefügig zu
machen:

namespace test {
class malloc {
std::size_t sz;

public:
malloc(std::size_t size) : sz(size) {}

template<typename T>
operator T*() { return (T*)std::malloc(sz); }
};
}

void bla() {
#ifdef NOMALLOCTEST
using std ::malloc;
#else
using test::malloc;
#endif

char* str = malloc(10); // ok (wenn test::malloc aktiv)
// ...
}

Fällt jemandem ein Fall ein, wo dies zu Problemen führen könnte?

Gruß,
Michael
Markus Schaaf (17.11.2003, 17:06)
"Michael Trocken" <s1234569> schrieb:

> class malloc {
> std::size_t sz;
> public:
> malloc(std::size_t size) : sz(size) {}
> template<typename T>
> operator T*() { return (T*)std::malloc(sz); }
> };


> Fällt jemandem ein Fall ein, wo dies zu Problemen führen könnte?


An Schnittstellen von Bibliotheken oder an Modulgrenzen werden in C
oft Zeiger auf Allocatorfunktionen übergeben.
Daniel Albuschat (18.11.2003, 09:15)
Markus Schaaf wrote:
> "Michael Trocken" <s1234569> schrieb:
>>Fällt jemandem ein Fall ein, wo dies zu Problemen führen könnte?

> An Schnittstellen von Bibliotheken oder an Modulgrenzen werden in C
> oft Zeiger auf Allocatorfunktionen übergeben.


An diesen (zumindest steltener, evtl. garnicht vorkommenden) Stellen,
reicht es dann aber, std::malloc zu schreiben. Namespace sei dank.

Die Idee finde ich uebrigens ziemlich gut... zumindest fuer diesen
Zweck. Und solange man darauf achtet, dass der (neue) C++ Code nicht
auch davon betroffen wird. Kannst du evtl. auch
berichten, ob es problemlos funktioniert hat? :-)

cu, Daniel
Florian Weimer (18.11.2003, 21:21)
s1234569 (Michael Trocken) writes:

[..]
> operator T*() { return (T*)std::malloc(sz); }
> };
> }


Nette Idee. Ob das auch funktioniert, um die leichten Unterschiede bei
den Prototypen in den POSIX-Headern einiger Systeme glattzubügeln?
Volker Glave (18.11.2003, 23:29)
s1234569 (Michael Trocken) wrote in message news:92b1
[..]
> namespace test {
> class malloc {
> std::size_t sz;


Doch wohl eher
const std::size_t sz;

> public:
> malloc(std::size_t size) : sz(size) {}
> template<typename T>
> operator T*() { return (T*)std::malloc(sz); }


Doch wohl eher
operator T*() const { return static_cast<T*>(std::malloc(sz)); }

[..]
> // ...
> }
> Fällt jemandem ein Fall ein, wo dies zu Problemen führen könnte?


Selbstverständlich. Mal beide Verfahren nebeneinander.

char* str1 = static_cast<char*>(std::malloc(10));
char* str2 = test::malloc(10);

Gut, klappt. Aber:

char* str1a = 1 + static_cast<char*>(std::malloc(10));
char* str2a = 1 + test::malloc(10); // line 29

"trocken.cpp", line 29: Error: Cannot use test::malloc::T* to initialize char*.

Gruß
Volker
Falk Tannhäuser (19.11.2003, 10:47)
Volker Glave wrote:
> Gut, klappt. Aber:
> char* str1a = 1 + static_cast<char*>(std::malloc(10));
> char* str2a = 1 + test::malloc(10); // line 29
> "trocken.cpp", line 29: Error: Cannot use test::malloc::T* to initialize char*.


Der Ausdruck '1 + malloc(10)' sollte in C aber auch nicht akzeptiert werden,
da 'void*' standardgemäß keine Zeigerarithmetik unterstützt.
Comeau <http://www.comeaucomputing.com/tryitout> verhält sich hier standardkonform,
während mein gcc 3.3.1 als "kreative Erweiterung" die Zeigerarithmetik durchführt
(so als ob sizeof(void) == 1 wäre). Nur mit -pedantic gibt es eine Warnung.

Schlussfolgerung: Das beschriebene Problem sollte bei standardkonformem C-Kode
(um dessen vereinfachte Portierung nach C++ es dem OP ging) nicht auftreten.

Falk
Michael Trocken (19.11.2003, 15:00)
volker.glave (Volker Glave) wrote
> s1234569 (Michael Trocken) wrote
> > Bei der Weiterverwertung von in C geschriebenem Quell-Kode [...]


> char* str1a = 1 + static_cast<char*>(std::malloc(10));
> char* str2a = 1 + test::malloc(10); // line 29
> "trocken.cpp", line 29: Error: Cannot use test::malloc::T*
> to initialize char*.


Lässt sich denn

char* str3;
str3 = 1 + malloc(10);

mit einem C-Compiler kompilieren?

Gruß,
Michael
Michael Trocken (19.11.2003, 15:34)
Daniel Albuschat <daniel> wrote in message news:a031
> Markus Schaaf wrote:
> An diesen (zumindest steltener, evtl. garnicht vorkommenden) Stellen,
> reicht es dann aber, std::malloc zu schreiben. Namespace sei dank.
> Die Idee finde ich uebrigens ziemlich gut... zumindest fuer diesen
> Zweck. Und solange man darauf achtet, dass der (neue) C++ Code nicht
> auch davon betroffen wird. Kannst du evtl. auch berichten, ob es
> problemlos funktioniert hat? :-)


Bei den paar Sachen, die ich bisher verwendet habe, ging es. Das ist
aber wohl nicht repräsentativ. Klar, dass die von Markus erwähnten
Allokatorfunktionen nicht in das Schema passen. Man müsste mal
beobachten, wie häufig das vorkommt.

Gruß,
Michael
Rolf Magnus (19.11.2003, 16:01)
Michael Trocken wrote:

> volker.glave (Volker Glave) wrote
> [...]
> Lässt sich denn
> char* str3;
> str3 = 1 + malloc(10);
> mit einem C-Compiler kompilieren?


Abgesehen davon: Wer würde auf die Idee kommen, das zu programmieren?
Thomas Maeder (19.11.2003, 16:11)
s1234569 (Michael Trocken) writes:

> Lässt sich denn
> char* str3;
> str3 = 1 + malloc(10);
> mit einem C-Compiler kompilieren?


Hoffentlich nicht.

Das Resultat müsste ja sizeof(void) hinter den Rückgabewert von malloc()
zeigen.
Michael Klemm (19.11.2003, 18:55)
Hi,

Rolf Magnus wrote:
>>Lässt sich denn
>> char* str3;
>> str3 = 1 + malloc(10);
>>mit einem C-Compiler kompilieren?

> Abgesehen davon: Wer würde auf die Idee kommen, das zu programmieren?


Jemand, der str3[-1] schreiben können möchte. Irgendwann in meinem
kurzen Leben stand sowas tatsächlich als Tip für C/C++-Programmierer.

Ist zwar unsauber, scheint aber machmal zu funktionieren :-)

-michael
Michael Trocken (20.11.2003, 09:02)
Thomas Maeder <maeder> wrote:
> s1234569 (Michael Trocken) writes:
> Hoffentlich nicht.
> Das Resultat müsste ja sizeof(void) hinter den Rückgabewert von malloc()
> zeigen.


Außer in dem von Falk Tannhäuser beschriebenen Fall (bei gcc 3.3.1 als
"kreative Erweiterung") könnte das vielleicht akzeptiert worden sein,
wenn kein Prototyp für malloc vorlag (so dass als Rückgabewert int
angenommen wurde).

Das könnte man eventuell so behandeln:

namespace test {
class malloc {
const std::size_t sz;
const int offs;

public:
malloc(std::size_t size) : sz(size), offs(0) {}
malloc(const malloc& m, int os) : sz(m.sz), offs(os) {}

template<typename T>
operator T*() const {
return static_cast<T*>(std::malloc(sz)) + offs; }
};

inline const malloc operator+(int val, const malloc& m) {
return malloc(m, val);
}
inline const malloc operator+(const malloc& m, int val) {
return malloc(m, val);
}
// etc.
}

Allerdings würde ich dann eher dazu übergehen, die Stelle mit dem
beschriebenen Code zu überarbeiten.

Gruß,
Michael
Michael Trocken (20.11.2003, 12:24)
s1234569 (Michael Trocken) wrote:
[...]
> namespace test {
> class malloc {
> const std::size_t sz;
> const int offs;
> public:
> malloc(std::size_t size) : sz(size), offs(0) {}
> malloc(const malloc& m, int os) : sz(m.sz), offs(os) {}
> template<typename T>
> operator T*() const {
> return static_cast<T*>(std::malloc(sz)) + offs; }


Statt dessen:

template<typename T>
operator T*() const { return static_cast<T*>(
static_cast<char*>(std::malloc(sz)) + offs); }

> };
> inline const malloc operator+(int val, const malloc& m) {
> return malloc(m, val);
> }
> inline const malloc operator+(const malloc& m, int val) {
> return malloc(m, val);
> }
> // etc.
> }


Gruß,
Michael
Michael Trocken (20.11.2003, 12:34)
Florian Weimer <fw> wrote in message news:cfsf
> s1234569 (Michael Trocken) writes:
> Nette Idee. Ob das auch funktioniert, um die leichten Unterschiede bei
> den Prototypen in den POSIX-Headern einiger Systeme glattzubügeln?


Um welche Unterschiede geht es dabei? Nur Rückgabe von void* wie bei
malloc oder auch andere Dinge?

Gruß,
Michael
Volker Glave (20.11.2003, 18:50)
Falk Tannhäuser <falk.tannhauser> wrote in message news:cd1c
> Volker Glave wrote:
> Der Ausdruck '1 + malloc(10)' sollte in C aber auch nicht akzeptiert werden,
> da 'void*' standardgemäß keine Zeigerarithmetik unterstützt.
> Comeau <http://www.comeaucomputing.com/tryitout> verhält sich hier standardkonform,
> während mein gcc 3.3.1 als "kreative Erweiterung" die Zeigerarithmetik durchführt
> (so als ob sizeof(void) == 1 wäre). Nur mit -pedantic gibt es eine Warnung.
> Schlussfolgerung: Das beschriebene Problem sollte bei standardkonformem C-Kode
> (um dessen vereinfachte Portierung nach C++ es dem OP ging) nicht auftreten.


Ok, dann halt so:

int i1 = NULL == static_cast<char*>(std::malloc(10));
int i2 = NULL == test::malloc(10); // line 32

"trocken.cpp", line 32: Error: The operation "int == test::malloc" is illegal.
1 Error(s) detected.

Volker
(2. Versuch, über Google Groups zu posten. 1. Versuch ist anscheinend
verschütt gegangen.)

Ähnliche Themen