This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Use malloca instead alloca
- From: OndÅej BÃlka <neleai at seznam dot cz>
- To: libc-alpha at sourceware dot org
- Date: Fri, 28 Dec 2012 14:29:08 +0100
- Subject: [PATCH] Use malloca instead alloca
As I described in http://sourceware.org/ml/libc-alpha/2012-12/msg00459.html
I looked into using malloca.
It has two advantages, first is to avoid allocation large arrays into
stack, second is simplifying code by reducing number of #ifdef's
Initialy I examined gnulib one but it uses hash tables and is hard to
inline so I wrote faster variant.
As example I added used it in argp/argp-help.c .
I did not do more general alloca detection that glibc uses.
Also it could be possible GNU extension for 2.18?
---
argp/argp-help.c | 23 ++++--------
malloc/malloca.h | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 109 insertions(+), 16 deletions(-)
create mode 100644 malloc/malloca.h
diff --git a/argp/argp-help.c b/argp/argp-help.c
index 80c2b7d..f0f74b4 100644
--- a/argp/argp-help.c
+++ b/argp/argp-help.c
@@ -25,20 +25,7 @@
#include <config.h>
#endif
-/* AIX requires this to be the first thing in the file. */
-#ifndef __GNUC__
-# if HAVE_ALLOCA_H || defined _LIBC
-# include <alloca.h>
-# else
-# ifdef _AIX
-#pragma alloca
-# else
-# ifndef alloca /* predefined by HP cc +Olibcalls */
-char *alloca ();
-# endif
-# endif
-# endif
-#endif
+#include <malloc/malloca.h>
#include <stdbool.h>
#include <stddef.h>
@@ -1310,11 +1297,12 @@ usage_long_opt (const struct argp_option *opt,
static void
hol_usage (struct hol *hol, argp_fmtstream_t stream)
{
+ char *short_no_arg_opts = NULL;
if (hol->num_entries > 0)
{
unsigned nentries;
struct hol_entry *entry;
- char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1);
+ short_no_arg_opts = malloca (strlen (hol->short_options) + 1);
char *snao_end = short_no_arg_opts;
/* First we put a list of short options without arguments. */
@@ -1343,6 +1331,7 @@ hol_usage (struct hol *hol, argp_fmtstream_t stream)
hol_entry_long_iterate (entry, usage_long_opt,
entry->argp->argp_domain, stream);
}
+ freea(short_no_arg_opts);
}
/* Make a HOL containing all levels of options in ARGP. CLUSTER is the
@@ -1547,6 +1536,7 @@ static void
_help (const struct argp *argp, const struct argp_state *state, FILE *stream,
unsigned flags, char *name)
{
+ char *pattern_levels = NULL;
int anything = 0; /* Whether we've output anything. */
struct hol *hol = 0;
argp_fmtstream_t fs;
@@ -1585,7 +1575,7 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream,
{
int first_pattern = 1, more_patterns;
size_t num_pattern_levels = argp_args_levels (argp);
- char *pattern_levels = alloca (num_pattern_levels);
+ pattern_levels = malloca (num_pattern_levels);
memset (pattern_levels, 0, num_pattern_levels);
@@ -1680,6 +1670,7 @@ Try `%s --help' or `%s --usage' for more information.\n"),
if (hol)
hol_free (hol);
+ freea (pattern_levels);
__argp_fmtstream_free (fs);
}
diff --git a/malloc/malloca.h b/malloc/malloca.h
new file mode 100644
index 0000000..fbae6e8
--- /dev/null
+++ b/malloc/malloca.h
@@ -0,0 +1,102 @@
+/* Safe automatic memory allocation.
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _MALLOCA_H
+#define _MALLOCA_H
+
+#include <alloca.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define ALLOCA_MC 0x2439a2431bca4812L
+#define MALLOC_MC 0x1bca48122439a243L
+
+/* AIX requires this to be the first thing in the file. */
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H || defined _LIBC
+# include <alloca.h>
+# else
+# ifdef _AIX
+#pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+#endif
+
+
+ /* malloca(N) is a safe variant of alloca(N). It allocates N bytes of
+ memory allocated on the stack or heap for large requests.
+ It must be freed using freea() before
+ the function returns. Upon failure, it returns NULL. */
+#if 1
+#define malloca(n) ({\
+ void *__r__ = NULL;\
+ if (n < 4096 - 8)\
+ {\
+ __r__ = alloca (n + sizeof (uint64_t));\
+ if (__r__)\
+ {\
+ *((uint64_t *)__r__)=ALLOCA_MC;\
+ __r__ += sizeof (uint64_t);\
+ }\
+ }\
+ if (!__r__)\
+ {\
+ __r__ = malloc (n + sizeof (uint64_t));\
+ if (__r__)\
+ {\
+ *((uint64_t *)__r__)=MALLOC_MC;\
+ __r__ += sizeof (uint64_t);\
+ }\
+ }\
+ __r__;\
+})
+
+#define freea(r) {\
+void *__r__ = r;\
+if (__r__)\
+ {\
+ __r__ -= sizeof (uint64_t);\
+ if (*((uint64_t *)__r__) == MALLOC_MC)\
+ free (__r__);\
+ else if (*((uint64_t *)__r__) != ALLOCA_MC) abort_freea();\
+ }\
+}
+
+static void abort_freea()
+{
+ fprintf(stderr, "double freea or corruption\n");
+ abort();
+}
+#else
+#define malloca malloc
+#define freea free
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MALLOCA_H */
--
1.7.4.4