views:

121

answers:

3

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?

+1  A: 

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
Yes, the former would be also fine. Shouldn't GCC do that already by default for all const variables?
+2  A: 

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
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).
A: 

This question is somewhat relevant:
http://stackoverflow.com/questions/718477/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.

Neeraj
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.