Gemeinsame C++-Laufzeitbibliothek unter Linux?
-
ich hab mal irgendwo was von --enable-shared gesehen
-
ich glaub mit der Option -rdynamic geht das vielleicht, aber die GCC Doku schweigt sich über die Option aus
-
Und wie würdet ihr das unter Linux dann machen, wenn ihr in einer .so was löschen wollt, was von einer anderen .so allokiert wurde?
Also jetzt ohne Delete()-Funktion die jede .so exportiertChrisM
-
eine (dyn.) library stellt doch eigentlich nur funktionen zur verfügung?
meine, egal ob du statisch oder dynamisch linkst, das was hinten rauskommt is das gleiche, nur das bei dynamischen linken der code nicht im programm drin ist. ausgeführt wird er aber meines erachtens trotzdem im programm. heist auch, dass variablen, die über eine lib geladen werden, trotzdem im stack (oder heap? weis grad nicht genau ;)) des programms bleiben. also hat jedes pogramm eigene variablen. oder ist das genau das gegenteil von dem was du willst? wenn ja, könnte dich ipc interessieren
-
Was ist ipc? Also bei Visual C++ kann man als Linktyp für die Standardbibliothek "Multithreaded DLL" einstellen, dann verwenden alle DLLs und die EXE eines Prozesses eine geteilte Version der Standardbibliothek und man kann daher Heapspeicher freigeben, egal in welchem anderen Modul er allokiert wurde.
ChrisM
-
ipc heisst "Inter-Process Communication"
probier doch einfach mal aus, ob das geht, mit dem freigeben von Speicher
-
Achso, das sieht gut aus, nur scheint mir das zu viel Arbeit und das Programm soll ja noch unter Windows laufen.
Außerdem laufen die DLLs unter Windows ja alle im gleichen Prozess und ich denk, wenn ich unter Linux eine .so lad, wird auch kein neuer Prozess gestartet, oder?Ich will einfach einen gemeinsamen Heap für den ganzen Prozess.
Oder muss man die Standardbibliothek wirklich immer statisch zur Executable linken lassen?ChrisM
-
Oder muss man die Standardbibliothek wirklich immer statisch zur Executable linken lassen?
Nein!
probier es doch einfach mal aus mit dem Freigeben des Speichers!
-
> Nun wollte ich fragen, ob es sowas auch unter Linux gibt, oder ob die
> Laufzeitbibliothek immer statisch zum Programm gelinkt werden muss?Per default erstellt der GCC immer Programme, die dynamisch gegen Shared Libraries (die *.so Dateien) gelinkt sind. Solltest du tatsächlich einmal etwas statisch compilieren wollen/müssen, musst du dem Compiler dies mit der Option -static mitteilen und eventuell gegen statische Bibliotheken (Dateiendung *.a; das Gegenstück zu *.so Dateien) linken.
> unter Windows gibt es in Visual C++ die Möglich, eine s.g. Multithreaded DLL
> Laufzeitbibliothek zu verwenden, d.h. die Laufzeitbibliothek wird zur
> Laufzeit aus msvcrt.dll geladen.Wenn es dir darum geht, dass du benötigte Bibliotheken nicht zur Compilezeit sondern erst später zur Laufzeit verwenden möchtest, dann solltest du dir mal die Manpage zu dlopen() anschauen:
dlopen(3)
http://www.freebsd.org/cgi/man.cgi?query=dlopen&apropos=0&sektion=0&manpath=SuSE+Linux%2Fi386+7.3&format=html (Manpage aus SuSE/Linux 7.3)
http://www.freebsd.org/cgi/man.cgi?query=dlopen&apropos=0&sektion=0&manpath=FreeBSD+5.0-RELEASE&format=html (Manpage aus FreeBSD 5.0)> Das hat z.B. den Vorteil, dass [...] mehrere DLLs, die [...] in
> einem Prozess laufen, auf den Heapspeicher der anderen DLLs zugreifen können
> und vor allem auch freigeben können.Hört sich verdammt nach IPC und Shared Memory an.
shmget(2)
http://www.freebsd.org/cgi/man.cgi?query=shmget&apropos=0&sektion=0&manpath=SuSE+Linux%2Fi386+7.3&format=html (Manpage aus SuSE/Linux 7.3)
http://www.freebsd.org/cgi/man.cgi?query=shmget&apropos=0&sektion=0&manpath=FreeBSD+5.0-RELEASE&format=html (Manpage aus FreeBSD 5.0)IPC:Shared Memory
http://www.cs.cf.ac.uk/Dave/C/node27.html#SECTION002700000000000000000Programming in C
UNIX System Calls and Subroutines using C,
http://www.cs.cf.ac.uk/Dave/C/CE.html
-
Original erstellt von ChrisM:
**Was ist ipc? Also bei Visual C++ kann man als Linktyp für die Standardbibliothek "Multithreaded DLL" einstellen, dann verwenden alle DLLs und die EXE eines Prozesses eine geteilte Version der Standardbibliothek und man kann daher Heapspeicher freigeben, egal in welchem anderen Modul er allokiert wurde.ChrisM**
Eine Shared Library (eine *.dll ist ja erst einmal auch nix anderes) enthält lediglich eine Ansammlung von Funktionen, die du in deinem Programm verwenden kannst. Wenn eine dieser Funktionen Speicher allokiert, kann dein Programm natürlich auf diesen Speicher zugreifen -- sofern dir die Funktion einen Zeiger auf den allokierten Speicher zur Verfügung stellt.
Eine Shared Library enthält kein ausführbares Programm (zumindest in der UNIX Welt nicht), das von sich aus Speicher allokiert/freigibt.
Dein Programm kann natürlich aus mehrere Prozessen oder aus mehrere Threads bestehen, die wieder untereinander (über Pipes oder Shared Memory) kommunizieren. Eine Bibliotheksfunktion kann ebenfalls mit Prozessen (siehe Manpage zu fork(2))oder Threads (siehe Dokumentation zu POSIX Threads) arbeiten.
Bradford Nichols, Dick Buttlar & Jacqueline Proulx Farrell
Pthreads Programming - A POSIX Standard for Better Multiprocessing
http://www.oreilly.de/catalog/pthread/Richard W. Stevens
UNIX Network Programming, Volume 2, Second Edition: Interprocess Communications, Prentice Hall, 1999, ISBN 0-13-081081-9.
http://www.kohala.com/start/unpv22e/unpv22e.html
Um "den Stevens" wirst du in der UNIX Programmierung eh nicht drum rumkommen.Bill Gallmeister
POSIX.4 - Programming for the Real World
[url]http://www.oreilly.de/catalog/posix4/index.html[/ur]
Insbesondere Kapitel 4 ("Chapter 4: Better Coordination: Messages, Shared Memory, and Synchronization Communicating Between Processes ")
Auszug aus dem Inhalt:Chapter 4: Better Coordination: Messages, Shared Memory, and Synchronization Communicating Between Processes
..POSIX.1 Communication: Pipes and FIFOs
..System V Message Queues
..POSIX.4 Message Queues
..POSIX.4 Shared Memory and File Mapping
..Synchronizing Multiple Processes
..Conclusion
..Exercises
-
Danke für die ganzen Infos, aber irgendwie habt ihr das Problem noch nicht ganz verstanden- oder ich nicht.
Also unter Windows bei C++ wird ja jedes Programm (auch eine DLL) zur C++-Standardbibliothek gelinkt, die ja auch u.a. new und delete implementiert. In dieser Bibliothek gibt es jetzt eine Liste von allen allokierten Speicherbereichen. Wenn ich jetzt delete aufrufe, wird erst geprüft, ob ich den Speicher überhaupt allokiert habe.
Wenn ich jetzt eine EXE habe, die eine DLL verwendet, haben beide die Standardbibliothek statisch gelinkt, d.h. sie haben getrennte "Heaplisten", was auch heißt, dass ich in der DLL keinen von der EXE allokierten Speicher freigeben kann und andersrum.
Nun kann man das umgehen, indem man dem Visual C++ sagt, dass man gerne die Standardbibliothek dynamisch als DLL gelinkt haben möchte. Jetzt liegt die Standardbibliothek in einer DLL (msvrt6.dll oder so heißt die) und jeweils ein Prozess hat eine "Heapliste".
Nun zu Linux: Kann ich unter Linux mit den Defaulteinstellungen in einer Executable Speicher freigeben, der in einer .so allokiert wurde und andersrum?
ChrisM
-
speicher wird nie IN einer so allokiert. eine so hat also keinen speicher. dynamischer speicher wird im datensegment des prozesses verwaltet. entweder von new oder malloc. (oder anderen methoden aus anderen sprachen).
dh du bekommst eine adresse zurück, die immer zum prozess gehört. über diese adresse wird dein speicher verwaltet. wenn du jetz ein adresse = malloc(10101) machst und du es dann wieder mit free(adresse) frei gibst, ist das egal in welcher lib das passiert oder wo auch immer, so lange es im gleichen programm passiert. dh du brauchst das nur wieder mit free freigeben.
wenn du eine lib haben willst, die resistent speicher allokieren kann, der der lib immer zur verfügung steht, dann musst du shm verwenden, weil der mit malloc allokierte speicher immer beim beenden des programm automatisch verschwindet.
malloc ist keine routine des betriebssystems sondern der stdlib. (für new gilt das gleiche). wenn ein prozess beendet wird, dann wird auch das datensegmente verschwinden. dh du weißt nicht mehr wo dein speicher war bzw vielleicht wird der schon wieder von einem anderen programm verwendet.die glibc hat sehr gute und einfach verständliche doku darüber. www.gnu.org. da steht alles genau drin.
hoffe, das hilft.
-
zusatz:
immer bei einem system bleiben.
mallocierter speicher free-en und newen speicher deletennie mischen.
-
Danke!
Nur warum löst es dann Windows so umständlich?
ChrisM
-
Unter Windows ist es genau das selbe1
-
Nein, unter Windows wird die Standardbibliothek statisch gelinkt und wenn ich in einer EXE Speicher allokiere, kann ich den in einer DLL nicht freigeben und andersrum!
Sonst krieg ich eine Debug Assertion Failed und der Speicher wird nicht freigeben!ChrisM
-
Original erstellt von ChrisM:
**Nein, unter Windows wird die Standardbibliothek statisch gelinkt und wenn ich in einer EXE Speicher allokiere, kann ich den in einer DLL nicht freigeben und andersrum!
Sonst krieg ich eine Debug Assertion Failed und der Speicher wird nicht freigeben!ChrisM**
Sicher, dass du da jetzt nicht mehrere Themen wild durcheinander würfelst? Wie lange programmierst du Win32? Wie lange unter Linux bzw. Unix?
Bitte belege deine Aussage mit einem kurzen, aber konkreten Beispiel an Hand dessen man nachvollziehen kann, *was* du wirklich meinst. Vielleicht drückst du dich nur etwas ungenau aus.
-
Also unter Windows programmier ich schon länger, aber unter Linux hab ich noch gar nicht programmiert. Mir gehts ja nur darum, dass das was ich jetzt programmiere, später auch bequem portierbar ist.
Beispiel:
// Diese Funktion ist in der DLL/.so!! int* ExportierteFunktion(void) { return new int; } // Die EXE: int main() { int* pTest = ExportierteFunktion(); // ExportierteFunktion() muss man natürlich vorher irgendwie laden, ich glaub unter Linux mit dlopen() oder so delete pTest; // HIER!!!!!!!! return 0; }
Die mit "hier" markierte Zeile geht z.B. unter Windows nur, wenn ich die shared Version der Laufzeitbibliothek verwende, sonst erhalte ich nur eine Debug Assertion, denn: Das new int, das in der DLL ausgeführt wird, wird in eine Liste in der Laufzeitbibliothek eingetragen (da steht dann drin, 4 Byte großer Speicherblock bei 0xirgendwas allokiert). Wenn ich jetzt bei "hier" den Speicherbereich wieder freigeben will, geht das nur, wenn die Liste die selbe ist, sonst findet das delete der Bibliothek die Speicherallokierung nicht in der Liste!
Und mit der Standardeinstellung wird die Standardbibliothek halt immer zu jeder EXE/DLL einzeln statisch gelinkt und man hat getrennte Liste (=Fehler).Deswegen würd ich jetzt wissen, ob sowas unter Linux geht oder noch einfacher:
Ist obiger Code unter Linux lauffähig?ChrisM
-
Gut, einfache Frage, würde sowas unter Linux funktioniert:
void Test(int *p) { delete p; // Speicher freigeben, der von anderem Modul allokiert wurde! }
Irgendeine Executable, die die .so benutzt:
// ... ::Test(new int); // Unter Windows gäbe das jetzt eine Debug Assertion, wenn ich nicht die gemeinsame Laufzeitbibliothek verwende! // ...
ChrisM
-
die Frage haben glaub ich alle mittlerweile verstanden.
Meine Antwort (zum 3. mal): probier es einfach mal aus, wenn es jemand wüsste, dann hätte er schon längst geantwortet