-1

(GNU) C offers at least two mechanisms for manipulating variable data on stack - the first one is the alloca function and its relatives (e.g. strdupa), and the second is the "Variable Lenght Array" feature.

The problem with alloca is that it doesn't seem to allocate continous regions in memory - the program

#include <alloca.h>
#include <stdio.h>

int main(void) {
    int *a = alloca(sizeof(int));
    int *b = alloca(sizeof(int));
    printf("b-a = %ld (%ld)", b - a, 
           (char *)b - (char *)a);
    return 0;
}

prints

b-a = -4 (-16)

which suggest that subsequent allocations possibly return quadruples of words (but I'd expect it to be implementation-specific - I tried this code only on my ARM-based phone).

Is there any "sanctioned" way of pushing single values on the stack, rather than allocating them with size that is known upfront?

I mean something like:

int x = 4;
push(x, sizeof(x))
int y = *(int *) pop(sizeof(x));
assert(x == y);

I'm looking for a solution that would work on both x86 and ARM. (I consider that studying ABIs of these platforms and writing macros that would expand to assembly that explicitly manipulates stack pointer would be an option, but I don't have time to explore this on my own)

Maciek Godek
  • 172
  • 12
  • Your question reads like you are one step from inventing recursive functions. Are you aware of that concept? If yes please highlight how/why recursion cannot be used to achieve what you try. – Yunnosch Aug 25 '20 at 08:47
  • 1
    This is very much an [XY problem](http://xyproblem.info/). What is the *real* problem you need to solve? Why do you need the space to be contiguous instead of platform-aligned? Why do you need to allocate dynamically of the stack to begin with? – Some programmer dude Aug 25 '20 at 08:49
  • @Yunnosch yes I am aware of the concept of recursive functions. Here, I am trying to write an s-expression parser, but such that it would store the parsed structure on the stack rather than allocate it from the heap. The parser is probably going to be recursive, but I'd just like to avoid heap allocation. – Maciek Godek Aug 25 '20 at 08:58
  • 2
    Re “… which shows that subsequent allocations return quadruples of words”: No, it does not. It showed the relative placement of two things in one test, not a rule for allocations in general. – Eric Postpischil Aug 25 '20 at 09:01
  • @Someprogrammerdude I need to allocate dynamically because the size of the resulting data structure is unknown until runtime. While I could use system's `malloc`, I sometimes need to run my code on the platforms where it's unavailable, so I'd like to see what is the potential of "stack programming" in C – Maciek Godek Aug 25 '20 at 09:02
  • As noted, this is an X-Y problem. Just use the objects/data you need and do not worry about where they are placed. – Eric Postpischil Aug 25 '20 at 09:04
  • @EricPostpischil good point. Fixed. (FWIW, I did run two tests, and the results were consistent, but I agree that it's not a sort of knowledge that can be relied on) – Maciek Godek Aug 25 '20 at 09:06
  • 2
    If you have a platform without `malloc`, then you probably have a platform with very small stack. – n. m. could be an AI Aug 25 '20 at 09:18
  • @EricPostpischil I don't really understand the argument. The sole fact that I have a choice between `malloc` and `alloca` means that I need some reason to choose one over the other. If I choose `malloc`, then I'd also need to worry about having to `free` it somehow. – Maciek Godek Aug 25 '20 at 09:19
  • [Using alloca is considered a bad practice](https://stackoverflow.com/questions/1018853/why-is-the-use-of-alloca-not-considered-good-practice), so use `malloc`. Your `push(x, sizeof(x))` and `pop(sizeof(x));` can be just implemented with a custom (dynamically or statically allocated) buffer. Also `int y = ` would allocate a variable on stack, so compiler would have to track which variables are on stack and which are on your stack... just `int y = x;` – KamilCuk Aug 25 '20 at 09:31
  • The question does not ask about `alloca` versus `malloc`. It mentions `alloca` versus variable-length arrays. And a comment says a solution is needed where `malloc` is not available. So, no, this is not a question of `alloca` versus `malloc`. If you cannot use `malloc`, then do not. – Eric Postpischil Aug 25 '20 at 09:33
  • If you need control over object positions because `alloca` may be inefficient, then simply define one array large enough for the work and keep your own pointer into it that you manipulate like a stack. – Eric Postpischil Aug 25 '20 at 09:36
  • @EricPostpischil I'm not sure what "large enough for the work" would mean. I'd need to choose an arbitrary number, really. Another thing I could do would be to have two passes of my algorithm - the first one to determine the required size, and the second that actually allocates. But this makes things more inefficient, because I might need to store the stream somewhere between passes. – Maciek Godek Aug 25 '20 at 09:55
  • @KamilCuk I don't consider the statement that "something is considered a bad practice" a convincing argument. The problem with allocating a custom buffer is that I'd need to decide the size of that buffer. As to the compiler allocating automatic variables, I presume it's capable of performing static analysis (either way, I can prearrange the variables myself) – Maciek Godek Aug 25 '20 at 10:00
  • @MaciekGodek: You have already chosen an arbitrary number. Or, rather, one has been chosen for you. The hardware stack provided by the operating system or other part of the C implementation has a limited size. It is often very limited compared to the memory available via `malloc`, typically 1-8 MiB in common general-purpose systems, less in embedded systems. If you need a solution that can accommodate a large size than you can allocated statically, then you cannot use `alloca`, since implementations of it generally use the stack. – Eric Postpischil Aug 25 '20 at 10:00
  • Your question asks “Is there a way to explicitly manipulate variable data on stack in GNU C?” No, there is not, not in the way the question asks. So there is your answer. Now you seem to be seeking something other than what you asked, some solution to a problem you have not clearly stated. Is `alloca` taking too much space? How do you know? What is this parsing you are doing? Why are you trying to do it on a system where `malloc` is not available? Free-standing C implementations without `malloc` are commonly quite constrained and not used for open-ended parsing. – Eric Postpischil Aug 25 '20 at 10:03
  • So, the question asked has been answered (“No”). To get a solution to the actual problem you are trying to solve, write up a proper description of that problem and enter a new question for it. – Eric Postpischil Aug 25 '20 at 10:04
  • 2
    `The problem with allocating a custom buffer is that I'd need to decide the size of that buffer` and this is a problem any bare-metal programmer has been struggling since the beginning. And dynamic allocation is the solution. Other solutions is over-allocating to a maximum possible size or writing algorithms in a smart way with recursion or like in CPL style. – KamilCuk Aug 25 '20 at 10:21

1 Answers1

0

No, there is not a supported way to explicitly manipulate variable data on the stack in GNU C in the way this question asks. There is no sanctioned way of pushing “single values” on the stack.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312