Das aligned_alloc() liefert einen undefined Fehler im gcc Linker, es sollte seit C11 unterstützt sein: https://en.cppreference.com/w/c/memory/aligned_alloc Warum ist es im arm-eabi-none noch nicht drin? Das (veraltete?) memalign() gibt es und tut es auch, ist aber doch irgendwie unschön weil nicht portabel?
Da wird nicht vom Compiler bereitgestellt, sondern von der C-Bibliothek. Welche benutzt du? Glibc (seit 2.16)? Musl (seit 0.9.5)? Newlib (seit 2.3.0)? ... Es hängt auch davon ab ob du mit -std=c11 (oder neuer) baust, ob die Header die Funktion deklarieren. Das Fehlen der Deklaration sollte aber keinen Linkerfehler hervorrufen, außer du baust in Wirklichkeit C++ Code.
Daniel schrieb: > außer du baust in Wirklichkeit C++ > Code. doch, das schon, es ist ein .cpp Modul. Aber warum soll das einen Unterschied machen, im header ist die Funktion vorhanden, sonst hätte der Compiler ja schon gemeckert. Newlib-nano oder Newlib, die Version muss ich nochmal kontrollieren. War gcc 10.irgendwas
Hätte ja sein können, dass du dir selbst eine Deklaration gebastelt hast, bei der dann das extern "C" fehlt. Dann stimmt der Symbolname bei Linken nicht. Wie gesagt, hat nix mit der Version von GCC zu tun.
aber ich installiere ja keine *lib getrennt, die wird mit der Toolchain installiert die mit der jeweiligen gcc Version kommt. Es geht um ARM embedded, arm-eabi-none für die Cortex-M.
J. S. schrieb: > die wird mit der Toolchain installiert die mit der jeweiligen gcc > Version kommt GCC pflegt keine Bibliotheken. Der verlässt sich nur darauf, dass die mit ihm ausgelieferten Bibliotheken sich entsprechend dem Standard verhalten. Insofern gibt es nicht "die Toolchain", die mit dem GCC ausgeliefert wird. Du musst schon Ross und Reiter benennen.
na das was man von arm developer als toolchan runterlädt, ich habe noch die Version gcc-arm-none-eabi-10-2020-q4-major-win32.zip Dann probiere ich es mal mit einer neueren Version. Aber ARM schreibt auch dazu:
1 | 6.5.5 Alignment of C heap storage |
2 | The standard C allocation functions C99 (7.20.3), such as malloc(), return storage aligned to the normal maximal |
3 | alignment, i.e. the largest alignment of any (standard) type. |
4 | Implementations may, but are not required to, provide a function to return heap storage of greater alignment. Suitable |
5 | functions are: |
6 | int posix_memalign(void **memptr, size_t alignment, size_t size ); |
7 | as defined in POSIX, or: |
8 | void *aligned_alloc(size_t alignment, size_t size); |
9 | as defined in C11 (7.22.3.1) |
also alles kann, nix muss?
:
Bearbeitet durch User
Erstmal kannst du dich ja generell nicht auf den C standard berufen wenn du C++ schreibst. Da kannst du dich genau so gut auf einen Java standard oder so berufen. Wenn du C++ schreibst ist der von dir gewählte C++ standard relevant also: *C++98 *C++03 *C++11 *C++14 *C++17 *C++20 Wenn du C schreibst der entsprechende C standard: *C89 *C90 *C95 *C99 *C11 *C17 Wenn du Annahmen aus c in c++ triffst und andersrum, dann wirst du oft solche Probleme haben... Wenn du willst dass sich alles genau so wie im C11 Standard verhält, dann solltest du das explizit mit angeben also -std=c11, aber das hat natürlich nicht zwingend den gewünschten effekt wenn du c++ schreibst.
Das was ARM als gcc-arm-none-eabi-10-2020-q4-major-win32.zip zum Download anbietet ist eine von ARM zusammengestellte Kombination aus - gcc 10.2.1 - binutils 2.34.1 - gdb 10.1.90 - newlib 3.3.0 Es ist die Aufgabe von newlib sowohl den Header als auch die Library für aligned_alloc bereitzustellen. Alle 132 libc.a, libg.a, libc_nano.a und libg_nano.a Libraries in dem Paket enthalten eine Implementation von aligned_alloc. Mit welcher Kommandozeile linkst du und wie lautet die genaue Fehlermeldung?
Wenn du schon C++ benutzt, warum dann nicht den C++ Mechanismus für Alignment? https://en.cppreference.com/w/cpp/types/aligned_storage
Daniel schrieb: > Paket enthalten eine Implementation von aligned_alloc. ja, es wurde auch nicht genau aligned_alloc angemeckert, sondern das benutzt posix_memalign und das fehlte. Ich compiliere mit gnu++17 oder c++17, im C++17 ist aligned_alloc übernommen worden. Habe jetzt die aktuelle Version gcc 10.3.1 installiert, damit funktioniert es ohne weitere Änderungen. In C++ sollte allerdings aligned_alloc im std namespace liegen, aber wenn ich std::aligned_alloc() aufrufe, dann gibts Mecker das es nicht im std namespace gefunden wird. Programmierer schrieb: > Wenn du schon C++ benutzt, warum dann nicht den C++ Mechanismus für > Alignment? schon wieder veraltet: (deprecated in C++23)
:
Bearbeitet durch User
Naja, posix_memalign ist Bestandteil des gesamten malloc-Pakets.
1 | The posix_memalign() function allocates size bytes of memory such that |
2 | the allocation's base address is a multiple of alignment, and returns |
3 | the allocation in the value pointed to by ptr. The requested alignment |
4 | must be a power of 2 at least as large as sizeof(void *). |
Das Backend für malloc muss man in der newlib eh selbst implementieren (sbrk). Warum sie aber dann für posix_memalign keine Implementierung haben, ist verwunderlich. Müsstest du schauen, wie du etwas bauen kannst, das zu dem passt, was da schon als malloc-Implementierung drin ist.
J. S. schrieb: > Daniel schrieb: >> Paket enthalten eine Implementation von aligned_alloc. > ja, es wurde auch nicht genau aligned_alloc angemeckert, sondern das > benutzt posix_memalign und das fehlte. Willst du uns vielleicht noch etwas mitteilen?
J. S. schrieb: > aber ich installiere ja keine *lib getrennt, die wird mit der Toolchain > installiert die mit der jeweiligen gcc Version kommt. Umgekehrt: gcc kommt als Teil der installierten Toolchain. Die Standard-Bibliothek auch. Es gibt auch keinen: J. S. schrieb: > gcc Linker denn der Linker ist ein weiterer Teil der Toolchain, aber nicht des Compilers.
Ich bin das Problem nochmal angegangen weil ich mit dem F7 Disco meine Heizungsüberwachung bauen möchte. Auf dem Disco F769 verhielt sich Ethernet anders duch einen Fehler in der Chip Rev. A, zum Test habe ich das Programm dann auf das Disco F746 portiert. Das hat diesen Fehler nicht, zickt jetzt aber bei aligned_alloc. Beim gcc 10.2 war die Funktion nicht passend für µC implementiert, danach wurde die Funktion geändert und verwendet jetzt intern _memalign_r() statt posix_align(). Ich habe jetzt die neuere gcc 11.3.1 installiert, mit newlib von 2022/08. Damit liefert aligned_alloc einen hardfault. Mit gcc 10.3.1 funktioniert es, auf dem F769 funktioniert es mit beiden gcc Versionen. Was kann da faul sein? Den Code der newlib habe ich heruntergeladen, der ist sehr mühselig zu lesen, die Funktionen werden per define hin und her umbenannt. Mein Testcode:
1 | #include "mbed.h" |
2 | |
3 | DigitalOut led(LED1); |
4 | |
5 | int main() |
6 | {
|
7 | size_t size = 1024; |
8 | |
9 | void *p1 = malloc(size); |
10 | printf("pointer p1: %p\n", p1); |
11 | fflush(stdout); |
12 | |
13 | void *p2 = aligned_alloc(32, size); |
14 | printf("pointer p2: %p\n", p2); |
15 | fflush(stdout); |
16 | |
17 | |
18 | while(true) { |
19 | led = !led; |
20 | ThisThread::sleep_for(1s); |
21 | }
|
22 | return 0; |
23 | }
|
Speicher ist satt vorhanden, das malloc funktioniert, das aligned_alloc führt zum hardfault mit Crashdump:
1 | pointer p1: 0x200030d8 |
2 | |
3 | ++ MbedOS Fault Handler ++ |
4 | |
5 | FaultType: HardFault |
6 | |
7 | Context: |
8 | R0 : 00000000 |
9 | R1 : FEADF7DC |
10 | R2 : 00000028 |
11 | R3 : DEADBEC5 |
12 | R4 : 00000020 |
13 | R5 : 00000408 |
14 | R6 : 200038F8 |
15 | R7 : 20000A10 |
16 | R8 : 20003918 |
17 | R9 : 00000000 |
18 | R10 : 00000000 |
19 | R11 : 00000000 |
20 | R12 : 08006D1D |
21 | SP : 20002E70 |
22 | LR : 08007C17 |
23 | PC : 08008938 |
24 | xPSR : A10F0000 |
25 | PSP : 20002E08 |
26 | MSP : 2004FFC0 |
27 | CPUID: 410FC271 |
28 | HFSR : 40000000 |
29 | MMFSR: 00000000 |
30 | BFSR : 00000082 |
31 | UFSR : 00000000 |
32 | DFSR : 00000000 |
33 | AFSR : 00000000 |
34 | BFAR : FEADF7E0 |
35 | Mode : Thread |
36 | Priv : Privileged |
37 | Stack: PSP |
38 | |
39 | -- MbedOS Fault Handler -- |
40 | |
41 | |
42 | |
43 | ++ MbedOS Error Info ++ |
44 | Error Status: 0x80FF013D Code: 317 Module: 255 |
45 | Error Message: Fault exception |
46 | Location: 0x8008938 |
47 | Error Value: 0x20001130 |
48 | Current Thread: main Id: 0x20002ECC Entry: 0x8007C71 StackSize: 0x1000 StackMem: 0x20001EA8 SP: 0x20002E70 |
49 | For more info, visit: https://mbed.com/s/error?error=0x80FF013D&osver=61600&core=0x410FC271&comp=2&ver=110300&tgt=DISCO_F746NG |
50 | -- MbedOS Error Info -- |
:
Bearbeitet durch User
Nimm doch einfach das normale alloc, das ist ausreichend aligned für alle Standard-Typen.
J. S. schrieb: > Die Cache Lines vom F7 möchten 32 Byte Alignment haben. Interessanter Punkt, wußte ich noch gar nicht. Und da Du Ethernet erwähntest, wird das dynamische Speichermanagement wohl für die IP-Pakete sein, die erst zur Laufzeit anfallen, weswegen die sonst übliche statische Allokation nicht so einfach wäre. Aber ob das Cache-Alignment da wirklich der Flaschenhals einer Heizungssteuerung wird, zumal Du ohnehin die Line-Grenzen überschreitest, sobald mehr als 32 Bytes im Paket sind? IP alleine hat ja schon 20 Bytes, plus nochmal 20 für TCP oder 8 für UDP.
Der crash jetzt ist im FatFS passiert, da wird ein Buffer angelegt der für das Lesen/Schreiben einiger Sektoren per DMA benutzt wird. Das Filesystem kann man mehrfach instanziieren, deshalb ist der Buffer da per malloc drin. Für den Cache mit den 32 Byte lines sollte der eben auch 32 Byte aligned sein, beim Cache clean kann sonst benachbarter Speicher überschrieben werden. Ist schon eine komplizierte Kiste. Jetzt habe ich es nochmal für den F769 übersetzt und da gibts nun auch einen Hardfault. Hmmm.... Alignment 16 und andere size beim alloc habe ich auch probiert, gleicher Fehler.
Oha. Macht das FS auch einen free() auf den Buffer? Wenn nicht, könntest Du ja rein zum Testen einen alloc-wrapper machen, der 32 Byte mehr alloziert und den ersten Pointer mit 32er-Alignment zurückgibt. free() geht darauf dann natürlich nicht, aber es wäre immerhin klar, daß es al Alignment liegt.
Ich kann den Fehler ja mit dem minimal Programm reproduzieren, deshalb ist mir die Anwendung von aligned_alloc jetzt erstmal egal. Wenn es die Funktion gibt, dann soll die auch funktionieren. So workarounds für aligned_alloc hatte ich schon probiert und war glücklich das es eine Funktion im Standard gibt. Nur scheint es mit der Implementierung zu hapern. In der newlib ist die jetzt drin, Keil hat eine eigene Lib und kennt die immer noch nicht.
:
Bearbeitet durch User
Die newlib ist unschuldig wie es aussieht, Mbed hat eine Statistik für malloc und die kommt durcheinander wenn memalign/aligned_alloc die Adresse des Blocks vom heap manipulieren. Schöner Fehler...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.