sizeof malloc in einer Funktion ohne Pointer aus main()

mogbo

Banned
Hallo,
wiedermal eine simple Frage, auf die ich keine Lösung finde

Code:
void
input(void * array, int * groesse)
{
  snprintf(array, * groesse, "Hello World\n", NULL);
}

int
main(void)
{
  void * test;
  int groesse = 50;

  test = malloc(groesse);


  // void * und int * in func input() uebergeben
  input(test, &groesse);

  printf("%s", test);

  free(test);
  return 0;
}

Gibt es eine Möglichkeit die Größe des "malloc" auf "void * test" herauszufinden, ohne es als int aus main() zu übergeben (quasi rein aus der Funktion raus)?
 
Zuletzt bearbeitet:
Gibt es eine Möglichkeit die Größe des "malloc" auf "void * test" herauszufinden, ohne es als int aus main() zu übergeben (quasi rein aus der Funktion raus)?

AFAIK musst du das selber tracken. Im Gegensatz zu "Strings", bei denen das Nullbyte als Endmarke dient, ist die Größe eines Speicherbereichs für beliebige Daten nur dir bekannt. Darum gibt es ja auch so viele Funktionen, denen man einen Puffer und dessen Größe übergeben muss.

Rob
 
AFAIK musst du das selber tracken. Im Gegensatz zu "Strings", bei denen das Nullbyte als Endmarke dient, ist die Größe eines Speicherbereichs für beliebige Daten nur dir bekannt. Darum gibt es ja auch so viele Funktionen, denen man einen Puffer und dessen Größe übergeben muss.

Rob
Vielen dank, dachte es gäbe evtl die Möglichkeit das OS zu fragen, wieviel Speicher es für den Pointer bereitgestellt hat
 
Nein, leider nicht. Das die Sprache / der Compiler / die Runtime die Länge von Speicherallokationen nicht kennen ist aus heutiger Sicht auch das vielleicht größte Problem von C.
 
Nein, leider nicht. Das die Sprache / der Compiler / die Runtime die Länge von Speicherallokationen nicht kennen ist aus heutiger Sicht auch das vielleicht größte Problem von C.
Finde die Sprache jedoch genau aus diesem Grund interessant, ich finde es klasse, dass man über seinen Code wirklich nachdenken muss. Für die Produktivität ist das natürlich ein Nachteil :)
 
Also deine malloc() Implementierung kennt natürlich die Größe der Allokation bzw. kann sie irgendwie(tm) herausfinden. Es gibt jedoch keine offizielle API um diese Größe zu erfragen. Denn oft speichert dein Allokator nicht die Größe nach der du gefragt hast sondern stattdessen die Größe, die er wirklich für dich gefunden hat.
 
Hi,

das queue(3) API / KPI boete einen Ansatzpunkt, fuer das Implementieren eines malloc(3)tracker.

Hier, ein grob vereinfachtes Beispiel, da zu bequem war smc_{get|delete|peak} hinzu scratchen:
Code:
#include <sys/queue.h>

 ...

#include <bla/blubb.>

 ...

#include <stdlib.h>
#include <time.h>


/*
 * Software context.
 * 
 * XXX: Access on tracker should be protected by 
 * XXX: some kind of mutual-exclusive lock, e. g.
 * XXX:
 * XXX:   int pthread_mutex_lock(pthread_mutex_t *mutex)
 * XXX: 
 */
struct malloc_softc {
	STAILQ_ENTRY(malloc_softc) 	msc_next;
/*
 * Some kind of indexing element, etc ... 
 */		
	time_t 	msc_id;
/*
 * By malloc(3) used size [still accepted as argument].
 */
	size_t 	msc_size;
/*
 * Maps to address, where alloc'd chunk starts.
 */
	caddr_t 	msc_object0;
/*
 * Self explanatory, because of
 * 
 *  ms_object1 = ms_object0 + ms_size
 */
	caddr_t 	msc_object1;
};

static STAILQ_HEAD(malloc_tracker, malloc_softc) msc_head = 
	STAILQ_HEAD_INITIALIZER(malloc_tracker);
/*
 * ...
 */ 

void * 	tracked_malloc(size_t);

/*
 * Ugly, but far more "beautiful" than some kind of
 * 
 *  struct malloc_softc msc[2048] msc_vec;
 * 
 * but, ... :)
 */
void *
tracked_malloc(size_t size)
{
	struct malloc_softc *msc;
/*
 * If 
 * 
 *  size in (N_+, +, e) 
 * 
 * where size denotes 
 * 
 *  identity e := 0
 * 
 * then leave. 
 */	 
	if (size == 0)
		return (NULL);
/*
 * Allocate element in set contains uniqe tracker and zero it out.
 */	 
	mscp = calloc(1, sizeof(struct malloc_softc));
	if (mscp == NULL) 
		return (NULL);

	msc->msc_id = time(NULL); 
	msc->msc_size = size; 	
/*
 * Allocate tracked object.
 */	
	msc->msc_object0 = malloc(msc->msc_size);
	if (msc->msc_object0 == NULL) {
/* 
 * If something went wrong, e. g, by errno tracked upcall 
 * denotes ENOMEM, ENOBUFS or something else, then release
 * by tracker bound resources.
 * 
 * Call of bzero(3) is not neccessary, but organization 
 * is half the battle? 
 */
		bzero(msc); 
		free(msc);
		msc = NULL;
		return (NULL);
	}
/*
 * Map "upper" bound of alloc'd chunk.
 */
	msc->msc_object1 = msc->msc_object0 + msc->msc_size;
/*
 * And finally, enqueue.
 */
	STAILQ_INSERT_HEAD(&msc_head, msc, msc_next);

	return (msc->msc_object0);
}

Hoffe fuer etwas Inspiration gesorgt zu haben?
 
Bin noch etwas ungeübt im lesen/verstehen von Code
Das reicht auch nicht, du musst dir zusätzlich die Doku zu queue(3) ansehen. Ich vermute auch, dass dir das nicht viel bringt - versuche dein Problem eben mit einem Puffer und einer zugehörigen Größe zu lösen. Du kannst auch, wenn du dabei nicht immer zwei Parameter übergeben willst, beides in einer Struktur zusammenfassen.

Rob
 
Wobei ein

Code:
void 	tracked_free(void *);

/*
 * Release alloc'd chunk of memory, iff still tracked.
 */
void 
tracked_free(void *ptr)
{	
	caddr_t *object;
	struct malloc_softc *msc;
	
	if ((object = ptr) == NULL)
		return;
/*
 * Seek..
 */	
	STAILQ_FOREACH_SAFE(msc, &msc_head, msc_next) {
/*
 * jump out ..
 */
	    if (msc->msc_object0 == object) 
			break;
	}
/*
 * or leave, if not found.
 */	
	if (msc == NULL) 
		return;
/*
 * Remove and destroy software-context..
 */
	STAILQ_REMOVE(&msc_head, msc, malloc_softc, msc_next);

	bzero(msc); 
	free(msc);

	msc = NULL;
/*
 * and release alloc'd chunk of memory. 
 */	
	bzero(ptr);
	free(ptr);
}

mir nicht verkneifen konnte.

:D

Getestet wurde jetzt das Kasperletheater nicht, denn es soll nur "inspirieren", da die Implementierung von malloc(3) an sich schon eine Steilvorlage fur das Implementieren eines Trackers ist.
 
Zuletzt bearbeitet von einem Moderator:
Das reicht auch nicht, du musst dir zusätzlich die Doku zu queue(3) ansehen. Ich vermute auch, dass dir das nicht viel bringt - versuche dein Problem eben mit einem Puffer und einer zugehörigen Größe zu lösen. Du kannst auch, wenn du dabei nicht immer zwei Parameter übergeben willst, beides in einer Struktur zusammenfassen.
Getestet wurde jetzt das Kasperletheater nicht, denn es soll nur "inspirieren", da die Implementierung von malloc(3) an sich schon eine Steilvorlage fur das Implementieren eines Trackers ist.
Ich sehe das bei mir momentan eher als Verständnisübung, daraus soll erstmal nichts produktives entstehen. Sobald es produktiv werden soll, werde ich definitiv queue(3) durcharbeiten

Das Übergeben von zwei Parametern ist auch kein Thema, ich wollte lediglich aus der Neugier heraus wissen, obs auch mit weniger geht :)
 
Es sei angemerkt, dass das
Code:
	mscp = calloc(1, sizeof(struct malloc_softc));
	if (mscp == NULL) 
		return (NULL);
durch
Code:
	msc = calloc(1, sizeof(struct malloc_softc));
	if (msc == NULL) 
		return (NULL);
sowie das
Code:
STAILQ_FOREACH_SAFE(msc, &msc_head, msc_next)
durch
Code:
STAILQ_FOREACH(msc, &msc_head, msc_next)
ersetzt werden wollen. Werde selbstverstaendlich das alles erklaeren bzw. erlaeutern, falls Fragen auftauchen.
 
Werde selbstverstaendlich das alles erklaeren bzw. erlaeutern, falls Fragen auftauchen.
Sorry, ich werd mich zu dem Thema nochmal in 1-2 Wochen melden, ich setze mich erstmal an das Thema queue.h, je öfter ich in die Manpage sehe, desto mehr Funktionen finde ich die ich mir eventuell doch mal verinnerlichen sollte
 
Der * aka Asterisk bzw. der Inhaltsoperator von
Code:
caddr_t *object;
in
Code:
void 	tracked_free(void *);
muss entfernt
Code:
caddr_t object;
werden [mein Fehler], da sonst
Code:
char **object
deklariert werde, weil
Code:
typedef char *      caddr_t;    /* core address */
definiert ist.
 
Zurück
Oben