Forum: Compiler & IDEs Malloc gibt immer 0x00 zurück. Linker file fehlerhaft? (LPC2214)


von Sven (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen

Ich habe ein Problem mit einem Programm auf einem LPC2214.

Es geht um folgenden C Code (nur zum testen, wie viel Speicher ich 
reservieren kann)
1
unsigned int counter = 0;
2
3
while (1)
4
{
5
  counter++;
6
  pointer = malloc(32);
7
  if (pointer == 0)
8
  {
9
    pointer++;  // Hier liegt nen breakpoint...
10
  }
11
}

So. Wenn ich jetzt in meinem Linker File
1
__end__ = .;
2
_end = .;
3
PROVIDE(end = .);

vor den Definitionen für die Stacks schreibe (wie in der angehängten 
Datei) kann ich 37 mal die 32 Byte reservieren.

Wenn ich den teil mit dem PROVIDE(end=.) ans Ende der Datei schreibe 
(wie es doch eigentlich richtig ist, oder?) bekomme ich von malloc IMMER 
0x00000000 zurück.

Einige Infos noch zur Umgebung:

Ich benutze Yagarto mit eclipse.
Version.txt von Yagarto:
1
This build of yagarto use the following versions:
2
3
binutils: 2.18
4
gcc:      4.3.2
5
newlib:   1.16.0
6
gdb:      6.8.50-20080308-cvs
7
8
(28.09.2008, mifi)

von Sven (Gast)


Lesenswert?

Mir fällt grade auf, dass 37*32Byte ja nur ca. 1k sind. Wenn ich mir die 
Ausgabe
1
Size of target .elf file:
2
arm-elf-size -B ./test.elf
3
   text     data      bss      dec      hex  filename
4
  16224     2100     2736    21060     5244  ./test.elf
angucke sollte da doch noch ein bisschen mehr zu holen sein.


Was mir noch aufgefallen ist: Wenn ich die Größe des USR_STACKS erhöhe 
(von jetzt 0x00000800 auf z.B. 0x00002000) kann ich mehr Speicher 
reservieren. Holt sich malloc den Speicher ausm stack? WTF?

von Tilo (Gast)


Lesenswert?

Wo sind die Syscall implementiert? ich würde dort die Funktion sbrk 
anschauen, die ist dafür zuständig, die richtige Adresse zurückzugeben.

Bei mir war es so, dass ich die newlib von Hand kompilieren musste 
(-DSMALL_MEMORY), da sonst immer 4kb Seiten verwendet wurden. Dabei ist 
bei mir der Heap gegen den Stack geknallt, was böse ausging.

von Sven (Gast)


Lesenswert?

Ich glaub ich nutze die libraries, die bei Yagarto dabei sind.

Was ich mich ja auch frage ist, wo gehört das PROVIDE(end = .); 
statement denn richtigerweise hin? Doch eigentlich ganz an das Ende, 
odeR?

Wie kompiliere ich denn das newlib gedöhns von Hand? Sowas hab ich noch 
nicht gemacht.

Oder könntest du mir deine selbst kompilierte library zukommen lassen?


Mir fällt noch was ein: Zu Hause musste ich eine eigene syscalls.c mit 
in mein Projekt werfen, da der linker irgendwie die Funktionen daraus 
nicht finden konnte. Könnte es schon helfen, diese Datei in das 
betroffene Projekt einzubinden?

von Tilo (Gast)


Lesenswert?

Ich hab das ganze für meinen MAc kompiliert, dass wird bei dir nicht so 
ohne weiteres laufen.

Die syscalls musst du selbst implementieren und die müssen im Projekt 
sein. Afaik gibts für die LPC Serie schon etwas Vorbereitetes.

Durchsuche das Forum nach newlib und syscalls, da solltest du schon 
etwas finden. Die fehlende Funktion sollte in etwa so aussehen:
1
extern char end[];              /*  end is set in the linker command   */
2
        /* file and is the end of statically   */
3
        /* allocated data (thus start of heap).  */
4
static char *heap_ptr;    /* Points to current end of the heap.  */
5
6
/************************** _sbrk_r *************************************
7
 * Support function. Adjusts end of heap to provide more memory to
8
 * memory allocator. Simple and dumb with no sanity checks.
9
 *  struct _reent *r -- re-entrancy structure, used by newlib to
10
 *                      support multiple threads of operation.
11
 *  ptrdiff_t nbytes -- number of bytes to add.
12
 *                      Returns pointer to start of new heap area.
13
 *
14
 *  Note:  This implementation is not thread safe (despite taking a
15
 *         _reent structure as a parameter).
16
 *         Since _s_r is not used in the current implementation, 
17
 *         the following messages must be suppressed.
18
 */
19
20
void * _sbrk_r(
21
    struct _reent *_s_r, 
22
    ptrdiff_t nbytes)
23
{
24
  char  *base;    /*  errno should be set to  ENOMEM on error  */
25
  if (!heap_ptr) {  /*  Initialize if first time through.  */
26
    heap_ptr = end;
27
  }
28
  base = heap_ptr;  /*  Point to end of heap.  */
29
  heap_ptr += nbytes;  /*  Increase heap.  */
30
  return base;    /*  Return pointer to start of new heap area.  */
31
}

von Sven (Gast)


Angehängte Dateien:

Lesenswert?

So.

Vielen Dank Tilo!!

Mit deinem Tip hab ich es ans laufen bekommen!
1
/* Register name faking - works in collusion with the linker.  */
2
register char * stack_ptr asm ("sp");
3
4
caddr_t _sbrk_r(struct _reent *r, int incr)
5
{
6
  extern char end asm ("end"); /* Defined by the linker.  */
7
  extern char __ram_end asm ("__ram_end"); // Hier auch, ram ende aus dem Linker file besorgen.
8
9
  static char * heap_end;
10
  char * prev_heap_end;
11
12
  if (heap_end == NULL)
13
    heap_end = &end;
14
15
  prev_heap_end = heap_end;
16
17
  if (heap_end + incr > &__ram_end)  // Hier musste ich mit dem ram ende vergleichen, da mein stack nach unten und mein heap nach oben wachsen soll.
18
  {
19
    /* Some of the libstdc++-v3 tests rely upon detecting
20
     out of memory errors, so do not abort here.  */
21
#if 0
22
    extern void abort (void);
23
24
    _write (1, "_sbrk: Heap and stack collision\n", 32);
25
26
    abort ();
27
#else
28
    errno = ENOMEM;
29
    return (caddr_t) -1;
30
#endif
31
  }
32
33
  heap_end += incr;
34
35
  return (caddr_t) prev_heap_end;
36
}

Im Linkerfile ist nun die definition für "end" am ende nach den Stacks.

Ich hoffe den anderen mit dem Problem kann durch mein Linkerfile und 
durch die angepassten Syscalls aus irgendeinem Beispielprojekt aus dem 
Netz geholfen werden...

Danke nochmal!

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.