8

Is it possible to have a (fixed) array which stores its elements in the read-only segment of the executable and not on the stack? I came up with this code but unfortunately it is very unflexible when it comes to adding, moving or deleting items. How do I verify that the strings are indeed stored in the read-only segment? I tried readelf -a file but it doesn't list the strings.

typedef struct {
        int len;
        int pos[100];
        char data[500];
} FixedStringArray;

const FixedStringArray items = {
        4,
        { 9, 14, 19, 24 },
        "LongWord1Word2Word3Word4"
} ;

char* GetItem(FixedStringArray *array, int idx, int *len) {
        if (idx >= array->len) {
                /* Out of range */
                *len = -1;
                return NULL;
        }

        if (idx > 0) {
                *len = array->pos[idx] - array->pos[idx - 1];
                return & array->data[array->pos[idx - 1]];
        }

        *len = array->pos[idx];
        return & array->data[0];
}

void PrintItem(FixedStringArray array, int idx) {
        int len;
        char *c;
        int i = 0;

        c = GetItem(&array, idx, &len);

        if (len == -1) return;

        while (i < len) {
                printf("%c", *c);
                *c++;
                i++;
        }
}

I am considering a script that automatically generates a struct for each array and uses the correct length for pos and data. Are there any concerns in terms of memory usage? Or would it be better to create one struct (like above) to fit all strings?

user206268
  • 908
  • 2
  • 8
  • 23

3 Answers3

31

I'm not sure I understand your question, but do you mean:

const char * const array[] = { "LongWord1", "Word2", "Word3", "Word4" };

This declares a constant array of pointers to constant characters.

OK, to avoid strlen, how about:

struct Str {
    size_t len;
    char *str;
};
#define STR(s) { sizeof(#s) - 1, #s }
const struct Str[] = { STR(LongWord1), STR(Word2), STR(Word3), STR(Word4) };
Richard Pennington
  • 19,673
  • 4
  • 43
  • 72
  • Okay, that would make things easier indeed but I prefer not to use NUL termination for strings. I do not want to depend on external functions such as strlen() just to get the length considering it can be also calculated during on compile time (using sizeof()-1). – user206268 Nov 29 '09 at 16:12
  • What does that "#" mean in front of the s? – Fra93 Jul 05 '17 at 13:30
  • # turns the macro argument into a string e.g. longword1 becomes "longword1". – Richard Pennington Jul 05 '17 at 13:36
1

Can't your C compiler stick any/all literal strings into read-only memory (e.g. VC++ with string pooling enabled)? Or do you explicitly require them to be stored sequentially in that way?

DrPizza
  • 17,882
  • 7
  • 41
  • 53
0

This question is somewhat relevant:
String Literals

As pointed out, the storage of string literals in ROM/RAM is platform/implementation dependent, you should not make any predictions for that. Also using a script to read and create array of appropriate sizes and store them is quite undesirable. You should better go for dynamic memory.

Community
  • 1
  • 1
sud03r
  • 19,109
  • 16
  • 77
  • 96
  • Thanks for the link. But how is the ROM/RAM difficulty related to my problem? I do not write to the string buffer during runtime. Since the elements are all fixed, there is no sense in using dynamic memory. – user206268 Nov 29 '09 at 16:24